Bug 1845311 - [Part 2] Use ChromeUtils.defineLazyGetter in more places r=arai,webcomp...
[gecko.git] / netwerk / test / unit / test_http_sfv.js
blob4b7ec9893c474ce786171ac390644e63eacafb07
1 "use strict";
3 const gService = Cc["@mozilla.org/http-sfv-service;1"].getService(
4   Ci.nsISFVService
5 );
7 add_task(async function test_sfv_bare_item() {
8   // tests bare item
9   let item_int = gService.newInteger(19);
10   Assert.equal(item_int.value, 19, "check bare item value");
12   let item_bool = gService.newBool(true);
13   Assert.equal(item_bool.value, true, "check bare item value");
14   item_bool.value = false;
15   Assert.equal(item_bool.value, false, "check bare item value");
17   let item_float = gService.newDecimal(145.45);
18   Assert.equal(item_float.value, 145.45);
20   let item_str = gService.newString("some_string");
21   Assert.equal(item_str.value, "some_string", "check bare item value");
23   let item_byte_seq = gService.newByteSequence("aGVsbG8=");
24   Assert.equal(item_byte_seq.value, "aGVsbG8=", "check bare item value");
26   let item_token = gService.newToken("*a");
27   Assert.equal(item_token.value, "*a", "check bare item value");
28 });
30 add_task(async function test_sfv_params() {
31   // test params
32   let params = gService.newParameters();
33   let bool_param = gService.newBool(false);
34   let int_param = gService.newInteger(15);
35   let decimal_param = gService.newDecimal(15.45);
37   params.set("bool_param", bool_param);
38   params.set("int_param", int_param);
39   params.set("decimal_param", decimal_param);
41   Assert.throws(
42     () => {
43       params.get("some_param");
44     },
45     /NS_ERROR_UNEXPECTED/,
46     "must throw exception as key does not exist in parameters"
47   );
48   Assert.equal(
49     params.get("bool_param").QueryInterface(Ci.nsISFVBool).value,
50     false,
51     "get parameter by key and check its value"
52   );
53   Assert.equal(
54     params.get("int_param").QueryInterface(Ci.nsISFVInteger).value,
55     15,
56     "get parameter by key and check its value"
57   );
58   Assert.equal(
59     params.get("decimal_param").QueryInterface(Ci.nsISFVDecimal).value,
60     15.45,
61     "get parameter by key and check its value"
62   );
63   Assert.deepEqual(
64     params.keys(),
65     ["bool_param", "int_param", "decimal_param"],
66     "check that parameters contain all the expected keys"
67   );
69   params.delete("int_param");
70   Assert.deepEqual(
71     params.keys(),
72     ["bool_param", "decimal_param"],
73     "check that parameter has been deleted"
74   );
76   Assert.throws(
77     () => {
78       params.delete("some_param");
79     },
80     /NS_ERROR_UNEXPECTED/,
81     "must throw exception upon attempt to delete by non-existing key"
82   );
83 });
85 add_task(async function test_sfv_inner_list() {
86   // create primitives for inner list
87   let item1_params = gService.newParameters();
88   item1_params.set("param_1", gService.newToken("*smth"));
89   let item1 = gService.newItem(gService.newDecimal(172.145865), item1_params);
91   let item2_params = gService.newParameters();
92   item2_params.set("param_1", gService.newBool(true));
93   item2_params.set("param_2", gService.newInteger(145454));
94   let item2 = gService.newItem(
95     gService.newByteSequence("weather"),
96     item2_params
97   );
99   // create inner list
100   let inner_list_params = gService.newParameters();
101   inner_list_params.set("inner_param", gService.newByteSequence("tests"));
102   let inner_list = gService.newInnerList([item1, item2], inner_list_params);
104   // check inner list members & params
105   let inner_list_members = inner_list.QueryInterface(Ci.nsISFVInnerList).items;
106   let inner_list_parameters = inner_list
107     .QueryInterface(Ci.nsISFVInnerList)
108     .params.QueryInterface(Ci.nsISFVParams);
109   Assert.equal(inner_list_members.length, 2, "check inner list length");
111   let inner_item1 = inner_list_members[0].QueryInterface(Ci.nsISFVItem);
112   Assert.equal(
113     inner_item1.value.QueryInterface(Ci.nsISFVDecimal).value,
114     172.145865,
115     "check inner list member value"
116   );
118   let inner_item2 = inner_list_members[1].QueryInterface(Ci.nsISFVItem);
119   Assert.equal(
120     inner_item2.value.QueryInterface(Ci.nsISFVByteSeq).value,
121     "weather",
122     "check inner list member value"
123   );
125   Assert.equal(
126     inner_list_parameters.get("inner_param").QueryInterface(Ci.nsISFVByteSeq)
127       .value,
128     "tests",
129     "get inner list parameter by key and check its value"
130   );
133 add_task(async function test_sfv_item() {
134   // create parameters for item
135   let params = gService.newParameters();
136   let param1 = gService.newBool(false);
137   let param2 = gService.newString("str_value");
138   let param3 = gService.newBool(true);
139   params.set("param_1", param1);
140   params.set("param_2", param2);
141   params.set("param_3", param3);
143   // create item field
144   let item = gService.newItem(gService.newToken("*abc"), params);
146   Assert.equal(
147     item.value.QueryInterface(Ci.nsISFVToken).value,
148     "*abc",
149     "check items's value"
150   );
151   Assert.equal(
152     item.params.get("param_1").QueryInterface(Ci.nsISFVBool).value,
153     false,
154     "get item parameter by key and check its value"
155   );
156   Assert.equal(
157     item.params.get("param_2").QueryInterface(Ci.nsISFVString).value,
158     "str_value",
159     "get item parameter by key and check its value"
160   );
161   Assert.equal(
162     item.params.get("param_3").QueryInterface(Ci.nsISFVBool).value,
163     true,
164     "get item parameter by key and check its value"
165   );
167   // check item field serialization
168   let serialized = item.serialize();
169   Assert.equal(
170     serialized,
171     `*abc;param_1=?0;param_2="str_value";param_3`,
172     "serialized output must match expected one"
173   );
176 add_task(async function test_sfv_list() {
177   // create primitives for List
178   let item1_params = gService.newParameters();
179   item1_params.set("param_1", gService.newToken("*smth"));
180   let item1 = gService.newItem(gService.newDecimal(145454.14568), item1_params);
182   let item2_params = gService.newParameters();
183   item2_params.set("param_1", gService.newBool(true));
184   let item2 = gService.newItem(
185     gService.newByteSequence("weather"),
186     item2_params
187   );
189   let inner_list = gService.newInnerList(
190     [item1, item2],
191     gService.newParameters()
192   );
194   // create list field
195   let list = gService.newList([item1, inner_list]);
197   // check list's members
198   let list_members = list.members;
199   Assert.equal(list_members.length, 2, "check list length");
201   // check list's member of item type
202   let member1 = list_members[0].QueryInterface(Ci.nsISFVItem);
203   Assert.equal(
204     member1.value.QueryInterface(Ci.nsISFVDecimal).value,
205     145454.14568,
206     "check list member's value"
207   );
208   let member1_parameters = member1.params;
209   Assert.equal(
210     member1_parameters.get("param_1").QueryInterface(Ci.nsISFVToken).value,
211     "*smth",
212     "get list member's parameter by key and check its value"
213   );
215   // check list's member of inner list type
216   let inner_list_members = list_members[1].QueryInterface(
217     Ci.nsISFVInnerList
218   ).items;
219   Assert.equal(inner_list_members.length, 2, "check inner list length");
221   let inner_item1 = inner_list_members[0].QueryInterface(Ci.nsISFVItem);
222   Assert.equal(
223     inner_item1.value.QueryInterface(Ci.nsISFVDecimal).value,
224     145454.14568,
225     "check inner list member's value"
226   );
228   let inner_item2 = inner_list_members[1].QueryInterface(Ci.nsISFVItem);
229   Assert.equal(
230     inner_item2.value.QueryInterface(Ci.nsISFVByteSeq).value,
231     "weather",
232     "check inner list member's value"
233   );
235   // check inner list member's params
236   list_members[1]
237     .QueryInterface(Ci.nsISFVInnerList)
238     .params.QueryInterface(Ci.nsISFVParams);
240   // check serialization of list field
241   let expected_serialized =
242     "145454.146;param_1=*smth, (145454.146;param_1=*smth :d2VhdGhlcg==:;param_1)";
243   let actual_serialized = list.serialize();
244   Assert.equal(
245     actual_serialized,
246     expected_serialized,
247     "serialized output must match expected one"
248   );
251 add_task(async function test_sfv_dictionary() {
252   // create primitives for dictionary field
254   // dict member1
255   let params1 = gService.newParameters();
256   params1.set("mp_1", gService.newBool(true));
257   params1.set("mp_2", gService.newDecimal(68.758602));
258   let member1 = gService.newItem(gService.newString("member_1"), params1);
260   // dict member2
261   let params2 = gService.newParameters();
262   let inner_item1 = gService.newItem(
263     gService.newString("inner_item_1"),
264     gService.newParameters()
265   );
266   let inner_item2 = gService.newItem(
267     gService.newToken("tok"),
268     gService.newParameters()
269   );
270   let member2 = gService.newInnerList([inner_item1, inner_item2], params2);
272   // dict member3
273   let params_3 = gService.newParameters();
274   params_3.set("mp_1", gService.newInteger(6586));
275   let member3 = gService.newItem(gService.newString("member_3"), params_3);
277   // create dictionary field
278   let dict = gService.newDictionary();
279   dict.set("key_1", member1);
280   dict.set("key_2", member2);
281   dict.set("key_3", member3);
283   // check dictionary keys
284   let expected = ["key_1", "key_2", "key_3"];
285   Assert.deepEqual(
286     expected,
287     dict.keys(),
288     "check dictionary contains all the expected keys"
289   );
291   // check dictionary members
292   Assert.throws(
293     () => {
294       dict.get("key_4");
295     },
296     /NS_ERROR_UNEXPECTED/,
297     "must throw exception as key does not exist in dictionary"
298   );
300   // let dict_member1 = dict.get("key_1").QueryInterface(Ci.nsISFVItem);
301   let dict_member2 = dict.get("key_2").QueryInterface(Ci.nsISFVInnerList);
302   let dict_member3 = dict.get("key_3").QueryInterface(Ci.nsISFVItem);
304   // Assert.equal(
305   //   dict_member1.value.QueryInterface(Ci.nsISFVString).value,
306   //   "member_1",
307   //   "check dictionary member's value"
308   // );
309   // Assert.equal(
310   //   dict_member1.params.get("mp_1").QueryInterface(Ci.nsISFVBool).value,
311   //   true,
312   //   "get dictionary member's parameter by key and check its value"
313   // );
314   // Assert.equal(
315   //   dict_member1.params.get("mp_2").QueryInterface(Ci.nsISFVDecimal).value,
316   //   "68.758602",
317   //   "get dictionary member's parameter by key and check its value"
318   // );
320   let dict_member2_items = dict_member2.QueryInterface(
321     Ci.nsISFVInnerList
322   ).items;
323   let dict_member2_params = dict_member2
324     .QueryInterface(Ci.nsISFVInnerList)
325     .params.QueryInterface(Ci.nsISFVParams);
326   Assert.equal(
327     dict_member2_items[0]
328       .QueryInterface(Ci.nsISFVItem)
329       .value.QueryInterface(Ci.nsISFVString).value,
330     "inner_item_1",
331     "get dictionary member of inner list type, and check inner list member's value"
332   );
333   Assert.equal(
334     dict_member2_items[1]
335       .QueryInterface(Ci.nsISFVItem)
336       .value.QueryInterface(Ci.nsISFVToken).value,
337     "tok",
338     "get dictionary member of inner list type, and check inner list member's value"
339   );
340   Assert.throws(
341     () => {
342       dict_member2_params.get("some_param");
343     },
344     /NS_ERROR_UNEXPECTED/,
345     "must throw exception as dict member's parameters are empty"
346   );
348   Assert.equal(
349     dict_member3.value.QueryInterface(Ci.nsISFVString).value,
350     "member_3",
351     "check dictionary member's value"
352   );
353   Assert.equal(
354     dict_member3.params.get("mp_1").QueryInterface(Ci.nsISFVInteger).value,
355     6586,
356     "get dictionary member's parameter by key and check its value"
357   );
359   // check serialization of Dictionary field
360   let expected_serialized = `key_1="member_1";mp_1;mp_2=68.759, key_2=("inner_item_1" tok), key_3="member_3";mp_1=6586`;
361   let actual_serialized = dict.serialize();
362   Assert.equal(
363     actual_serialized,
364     expected_serialized,
365     "serialized output must match expected one"
366   );
368   // check deleting dict member
369   dict.delete("key_2");
370   Assert.deepEqual(
371     dict.keys(),
372     ["key_1", "key_3"],
373     "check that dictionary member has been deleted"
374   );
376   Assert.throws(
377     () => {
378       dict.delete("some_key");
379     },
380     /NS_ERROR_UNEXPECTED/,
381     "must throw exception upon attempt to delete by non-existing key"
382   );
385 add_task(async function test_sfv_item_parsing() {
386   Assert.ok(gService.parseItem(`"str"`), "input must be parsed into Item");
387   Assert.ok(gService.parseItem("12.35;a "), "input must be parsed into Item");
388   Assert.ok(gService.parseItem("12.35;  a "), "input must be parsed into Item");
389   Assert.ok(gService.parseItem("12.35    "), "input must be parsed into Item");
391   Assert.throws(
392     () => {
393       gService.parseItem("12.35;\ta ");
394     },
395     /NS_ERROR_FAILURE/,
396     "item parsing must fail: invalid parameters delimiter"
397   );
399   Assert.throws(
400     () => {
401       gService.parseItem("125666.3565648855455");
402     },
403     /NS_ERROR_FAILURE/,
404     "item parsing must fail: decimal too long"
405   );
408 add_task(async function test_sfv_list_parsing() {
409   Assert.ok(
410     gService.parseList(
411       "(?1;param_1=*smth   :d2VhdGhlcg==:;param_1;param_2=145454);inner_param=:d2VpcmR0ZXN0cw==:"
412     ),
413     "input must be parsed into List"
414   );
415   Assert.ok("a, (b c)", "input must be parsed into List");
417   Assert.throws(() => {
418     gService.parseList("?tok", "list parsing must fail");
419   }, /NS_ERROR_FAILURE/);
421   Assert.throws(() => {
422     gService.parseList(
423       "a, (b, c)",
424       "list parsing must fail: invalid delimiter within inner list"
425     );
426   }, /NS_ERROR_FAILURE/);
428   Assert.throws(
429     () => {
430       gService.parseList("a, b c");
431     },
432     /NS_ERROR_FAILURE/,
433     "list parsing must fail: invalid delimiter"
434   );
437 add_task(async function test_sfv_dict_parsing() {
438   Assert.ok(
439     gService.parseDictionary(`abc=123;a=1;b=2, def=456, ghi=789;q=9;r="+w"`),
440     "input must be parsed into Dictionary"
441   );
442   Assert.ok(
443     gService.parseDictionary("a=1\t,\t\t\t   c=*"),
444     "input must be parsed into Dictionary"
445   );
446   Assert.ok(
447     gService.parseDictionary("a=1\t,\tc=*    \t\t"),
448     "input must be parsed into Dictionary"
449   );
451   Assert.throws(
452     () => {
453       gService.parseDictionary("a=1\t,\tc=*,");
454     },
455     /NS_ERROR_FAILURE/,
456     "dictionary parsing must fail: trailing comma"
457   );
459   Assert.throws(
460     () => {
461       gService.parseDictionary("a=1 c=*");
462     },
463     /NS_ERROR_FAILURE/,
464     "dictionary parsing must fail: invalid delimiter"
465   );
467   Assert.throws(
468     () => {
469       gService.parseDictionary("INVALID_key=1, c=*");
470     },
471     /NS_ERROR_FAILURE/,
472     "dictionary parsing must fail: invalid key format, can't be in uppercase"
473   );
476 add_task(async function test_sfv_list_parse_serialize() {
477   let list_field = gService.parseList("1  ,  42, (42 43)");
478   Assert.equal(
479     list_field.serialize(),
480     "1, 42, (42 43)",
481     "serialized output must match expected one"
482   );
484   // create new inner list with parameters
485   function params() {
486     let inner_list_params = gService.newParameters();
487     inner_list_params.set("key1", gService.newString("value1"));
488     inner_list_params.set("key2", gService.newBool(true));
489     inner_list_params.set("key3", gService.newBool(false));
490     return inner_list_params;
491   }
493   function changeMembers() {
494     // set one of list members to inner list and check it's serialized as expected
495     let members = list_field.members;
496     members[1] = gService.newInnerList(
497       [
498         gService.newItem(
499           gService.newDecimal(-1865.75653),
500           gService.newParameters()
501         ),
502         gService.newItem(gService.newToken("token"), gService.newParameters()),
503         gService.newItem(
504           gService.newString(`no"yes`),
505           gService.newParameters()
506         ),
507       ],
508       params()
509     );
510     return members;
511   }
513   list_field.members = changeMembers();
515   Assert.equal(
516     list_field.serialize(),
517     `1, (-1865.757 token "no\\"yes");key1="value1";key2;key3=?0, (42 43)`,
518     "update list member and check list is serialized as expected"
519   );
522 add_task(async function test_sfv_dict_parse_serialize() {
523   let dict_field = gService.parseDictionary(
524     "a=1,     b; foo=*, \tc=3, \t     \tabc=123;a=1;b=2\t"
525   );
526   Assert.equal(
527     dict_field.serialize(),
528     "a=1, b;foo=*, c=3, abc=123;a=1;b=2",
529     "serialized output must match expected one"
530   );
532   // set new value for existing dict's key
533   dict_field.set(
534     "a",
535     gService.newItem(gService.newInteger(165), gService.newParameters())
536   );
538   // add new member to dict
539   dict_field.set(
540     "key",
541     gService.newItem(gService.newDecimal(45.0), gService.newParameters())
542   );
544   // check dict is serialized properly after the above changes
545   Assert.equal(
546     dict_field.serialize(),
547     "a=165, b;foo=*, c=3, abc=123;a=1;b=2, key=45.0",
548     "update dictionary members and dictionary list is serialized as expected"
549   );
552 add_task(async function test_sfv_list_parse_more() {
553   // check parsing of multiline header of List type
554   let list_field = gService.parseList("(12 abc), 12.456\t\t   ");
555   list_field.parseMore("11, 15, tok");
556   Assert.equal(
557     list_field.serialize(),
558     "(12 abc), 12.456, 11, 15, tok",
559     "multi-line field value parsed and serialized successfully"
560   );
562   // should fail parsing one more line
563   Assert.throws(
564     () => {
565       list_field.parseMore("(tk\t1)");
566     },
567     /NS_ERROR_FAILURE/,
568     "line parsing must fail: invalid delimiter in inner list"
569   );
570   Assert.equal(
571     list_field.serialize(),
572     "(12 abc), 12.456, 11, 15, tok",
573     "parsed value must not change if parsing one more line of header fails"
574   );
577 add_task(async function test_sfv_dict_parse_more() {
578   // check parsing of multiline header of Dictionary type
579   let dict_field = gService.parseDictionary("");
580   dict_field.parseMore("key2=?0, key3=?1, key4=itm");
581   dict_field.parseMore("key1,    key5=11, key4=45");
583   Assert.equal(
584     dict_field.serialize(),
585     "key2=?0, key3, key4=45, key1, key5=11",
586     "multi-line field value parsed and serialized successfully"
587   );
589   // should fail parsing one more line
590   Assert.throws(
591     () => {
592       dict_field.parseMore("c=12, _k=13");
593     },
594     /NS_ERROR_FAILURE/,
595     "line parsing must fail: invalid key format"
596   );