Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /*
2 * Tests for imgITools
3 */
5 const Ci = Components.interfaces;
6 const Cc = Components.classes;
9 /*
10 * dumpToFile()
11 *
12 * For test development, dumps the specified array to a file.
13 * Call |dumpToFile(outData);| in a test to file to a file.
14 */
15 function dumpToFile(aData) {
16 var outputFile = do_get_tempdir();
17 outputFile.append("testdump.png");
19 var outputStream = Cc["@mozilla.org/network/file-output-stream;1"].
20 createInstance(Ci.nsIFileOutputStream);
21 // WR_ONLY|CREAT|TRUNC
22 outputStream.init(outputFile, 0x02 | 0x08 | 0x20, 0644, null);
24 var bos = Cc["@mozilla.org/binaryoutputstream;1"].
25 createInstance(Ci.nsIBinaryOutputStream);
26 bos.setOutputStream(outputStream);
28 bos.writeByteArray(aData, aData.length);
30 outputStream.close();
31 }
34 /*
35 * getFileInputStream()
36 *
37 * Returns an input stream for the specified file.
38 */
39 function getFileInputStream(aFile) {
40 var inputStream = Cc["@mozilla.org/network/file-input-stream;1"].
41 createInstance(Ci.nsIFileInputStream);
42 // init the stream as RD_ONLY, -1 == default permissions.
43 inputStream.init(aFile, 0x01, -1, null);
45 // Blah. The image decoders use ReadSegments, which isn't implemented on
46 // file input streams. Use a buffered stream to make it work.
47 var bis = Cc["@mozilla.org/network/buffered-input-stream;1"].
48 createInstance(Ci.nsIBufferedInputStream);
49 bis.init(inputStream, 1024);
51 return bis;
52 }
55 /*
56 * streamToArray()
57 *
58 * Consumes an input stream, and returns its bytes as an array.
59 */
60 function streamToArray(aStream) {
61 var size = aStream.available();
63 // use a binary input stream to grab the bytes.
64 var bis = Cc["@mozilla.org/binaryinputstream;1"].
65 createInstance(Ci.nsIBinaryInputStream);
66 bis.setInputStream(aStream);
68 var bytes = bis.readByteArray(size);
69 if (size != bytes.length)
70 throw "Didn't read expected number of bytes";
72 return bytes;
73 }
76 /*
77 * compareArrays
78 *
79 * Compares two arrays, and throws if there's a difference.
80 */
81 function compareArrays(aArray1, aArray2) {
82 do_check_eq(aArray1.length, aArray2.length);
84 for (var i = 0; i < aArray1.length; i++)
85 if (aArray1[i] != aArray2[i])
86 throw "arrays differ at index " + i;
87 }
90 /*
91 * checkExpectedError
92 *
93 * Checks to see if a thrown error was expected or not, and if it
94 * matches the expected value.
95 */
96 function checkExpectedError (aExpectedError, aActualError) {
97 if (aExpectedError) {
98 if (!aActualError)
99 throw "Didn't throw as expected (" + aExpectedError + ")";
101 if (!aExpectedError.test(aActualError))
102 throw "Threw (" + aActualError + "), not (" + aExpectedError;
104 // We got the expected error, so make a note in the test log.
105 dump("...that error was expected.\n\n");
106 } else if (aActualError) {
107 throw "Threw unexpected error: " + aActualError;
108 }
109 }
112 function run_test() {
114 try {
117 /* ========== 0 ========== */
118 var testnum = 0;
119 var testdesc = "imgITools setup";
120 var err = null;
122 var imgTools = Cc["@mozilla.org/image/tools;1"].
123 getService(Ci.imgITools);
125 if (!imgTools)
126 throw "Couldn't get imgITools service"
128 // Ugh, this is an ugly hack. The pixel values we get in Windows are sometimes
129 // +/- 1 value compared to other platforms, so we need to compare against a
130 // different set of reference images. nsIXULRuntime.OS doesn't seem to be
131 // available in xpcshell, so we'll use this as a kludgy way to figure out if
132 // we're running on Windows.
133 var isWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
136 /* ========== 1 ========== */
137 testnum++;
138 testdesc = "test decoding a PNG";
140 // 64x64 png, 8415 bytes.
141 var imgName = "image1.png";
142 var inMimeType = "image/png";
143 var imgFile = do_get_file(imgName);
145 var istream = getFileInputStream(imgFile);
146 do_check_eq(istream.available(), 8415);
148 // Use decodeImageData for this test even though it's deprecated to ensure that
149 // it correctly forwards to decodeImage and continues to work.
150 var outParam = { value: null };
151 imgTools.decodeImageData(istream, inMimeType, outParam);
152 var container = outParam.value;
154 // It's not easy to look at the pixel values from JS, so just
155 // check the container's size.
156 do_check_eq(container.width, 64);
157 do_check_eq(container.height, 64);
160 /* ========== 2 ========== */
161 testnum++;
162 testdesc = "test encoding a scaled JPEG";
164 // we'll reuse the container from the previous test
165 istream = imgTools.encodeScaledImage(container, "image/jpeg", 16, 16);
167 var encodedBytes = streamToArray(istream);
168 // Get bytes for exected result
169 var refName = "image1png16x16.jpg";
170 var refFile = do_get_file(refName);
171 istream = getFileInputStream(refFile);
172 do_check_eq(istream.available(), 1078);
173 var referenceBytes = streamToArray(istream);
175 // compare the encoder's output to the reference file.
176 compareArrays(encodedBytes, referenceBytes);
179 /* ========== 3 ========== */
180 testnum++;
181 testdesc = "test encoding an unscaled JPEG";
183 // we'll reuse the container from the previous test
184 istream = imgTools.encodeImage(container, "image/jpeg");
185 encodedBytes = streamToArray(istream);
187 // Get bytes for exected result
188 refName = "image1png64x64.jpg";
189 refFile = do_get_file(refName);
190 istream = getFileInputStream(refFile);
191 do_check_eq(istream.available(), 4503);
192 referenceBytes = streamToArray(istream);
194 // compare the encoder's output to the reference file.
195 compareArrays(encodedBytes, referenceBytes);
198 /* ========== 4 ========== */
199 testnum++;
200 testdesc = "test decoding a JPEG";
202 // 32x32 jpeg, 3494 bytes.
203 imgName = "image2.jpg";
204 inMimeType = "image/jpeg";
205 imgFile = do_get_file(imgName);
207 istream = getFileInputStream(imgFile);
208 do_check_eq(istream.available(), 3494);
210 container = imgTools.decodeImage(istream, inMimeType);
212 // It's not easy to look at the pixel values from JS, so just
213 // check the container's size.
214 do_check_eq(container.width, 32);
215 do_check_eq(container.height, 32);
218 /* ========== 5 ========== */
219 testnum++;
220 testdesc = "test encoding a scaled PNG";
222 if (!isWindows) {
223 // we'll reuse the container from the previous test
224 istream = imgTools.encodeScaledImage(container, "image/png", 16, 16);
226 encodedBytes = streamToArray(istream);
227 // Get bytes for exected result
228 refName = isWindows ? "image2jpg16x16-win.png" : "image2jpg16x16.png";
229 refFile = do_get_file(refName);
230 istream = getFileInputStream(refFile);
231 do_check_eq(istream.available(), 948);
232 referenceBytes = streamToArray(istream);
234 // compare the encoder's output to the reference file.
235 compareArrays(encodedBytes, referenceBytes);
236 }
239 /* ========== 6 ========== */
240 testnum++;
241 testdesc = "test encoding an unscaled PNG";
243 if (!isWindows) {
244 // we'll reuse the container from the previous test
245 istream = imgTools.encodeImage(container, "image/png");
246 encodedBytes = streamToArray(istream);
248 // Get bytes for exected result
249 refName = isWindows ? "image2jpg32x32-win.png" : "image2jpg32x32.png";
250 refFile = do_get_file(refName);
251 istream = getFileInputStream(refFile);
252 do_check_eq(istream.available(), 3105);
253 referenceBytes = streamToArray(istream);
255 // compare the encoder's output to the reference file.
256 compareArrays(encodedBytes, referenceBytes);
257 }
260 /* ========== 7 ========== */
261 testnum++;
262 testdesc = "test decoding a ICO";
264 // 16x16 ico, 1406 bytes.
265 imgName = "image3.ico";
266 inMimeType = "image/x-icon";
267 imgFile = do_get_file(imgName);
269 istream = getFileInputStream(imgFile);
270 do_check_eq(istream.available(), 1406);
272 container = imgTools.decodeImage(istream, inMimeType);
274 // It's not easy to look at the pixel values from JS, so just
275 // check the container's size.
276 do_check_eq(container.width, 16);
277 do_check_eq(container.height, 16);
280 /* ========== 8 ========== */
281 testnum++;
282 testdesc = "test encoding a scaled PNG"; // note that we're scaling UP
284 // we'll reuse the container from the previous test
285 istream = imgTools.encodeScaledImage(container, "image/png", 32, 32);
286 encodedBytes = streamToArray(istream);
288 // Get bytes for exected result
289 refName = "image3ico32x32.png";
290 refFile = do_get_file(refName);
291 istream = getFileInputStream(refFile);
292 do_check_eq(istream.available(), 2285);
293 referenceBytes = streamToArray(istream);
295 // compare the encoder's output to the reference file.
296 compareArrays(encodedBytes, referenceBytes);
299 /* ========== 9 ========== */
300 testnum++;
301 testdesc = "test encoding an unscaled PNG";
303 // we'll reuse the container from the previous test
304 istream = imgTools.encodeImage(container, "image/png");
305 encodedBytes = streamToArray(istream);
307 // Get bytes for exected result
308 refName = "image3ico16x16.png";
309 refFile = do_get_file(refName);
310 istream = getFileInputStream(refFile);
311 do_check_eq(istream.available(), 330);
312 referenceBytes = streamToArray(istream);
314 // compare the encoder's output to the reference file.
315 compareArrays(encodedBytes, referenceBytes);
318 /* ========== 10 ========== */
319 testnum++;
320 testdesc = "test decoding a GIF";
322 // 32x32 gif, 1809 bytes.
323 imgName = "image4.gif";
324 inMimeType = "image/gif";
325 imgFile = do_get_file(imgName);
327 istream = getFileInputStream(imgFile);
328 do_check_eq(istream.available(), 1809);
330 container = imgTools.decodeImage(istream, inMimeType);
332 // It's not easy to look at the pixel values from JS, so just
333 // check the container's size.
334 do_check_eq(container.width, 32);
335 do_check_eq(container.height, 32);
337 /* ========== 11 ========== */
338 testnum++;
339 testdesc = "test encoding an unscaled ICO with format options " +
340 "(format=bmp;bpp=32)";
342 // we'll reuse the container from the previous test
343 istream = imgTools.encodeImage(container,
344 "image/vnd.microsoft.icon",
345 "format=bmp;bpp=32");
346 encodedBytes = streamToArray(istream);
348 // Get bytes for exected result
349 refName = "image4gif32x32bmp32bpp.ico";
350 refFile = do_get_file(refName);
351 istream = getFileInputStream(refFile);
352 do_check_eq(istream.available(), 4286);
353 referenceBytes = streamToArray(istream);
355 // compare the encoder's output to the reference file.
356 compareArrays(encodedBytes, referenceBytes);
358 /* ========== 12 ========== */
359 testnum++;
360 testdesc = "test encoding a scaled ICO with format options " +
361 "(format=bmp;bpp=32)";
363 // we'll reuse the container from the previous test
364 istream = imgTools.encodeScaledImage(container,
365 "image/vnd.microsoft.icon",
366 16,
367 16,
368 "format=bmp;bpp=32");
369 encodedBytes = streamToArray(istream);
371 // Get bytes for exected result
372 refName = "image4gif16x16bmp32bpp.ico";
373 refFile = do_get_file(refName);
374 istream = getFileInputStream(refFile);
375 do_check_eq(istream.available(), 1150);
376 referenceBytes = streamToArray(istream);
378 // compare the encoder's output to the reference file.
379 compareArrays(encodedBytes, referenceBytes);
381 /* ========== 13 ========== */
382 testnum++;
383 testdesc = "test encoding an unscaled ICO with format options " +
384 "(format=bmp;bpp=24)";
386 // we'll reuse the container from the previous test
387 istream = imgTools.encodeImage(container,
388 "image/vnd.microsoft.icon",
389 "format=bmp;bpp=24");
390 encodedBytes = streamToArray(istream);
392 // Get bytes for exected result
393 refName = "image4gif32x32bmp24bpp.ico";
394 refFile = do_get_file(refName);
395 istream = getFileInputStream(refFile);
396 do_check_eq(istream.available(), 3262);
397 referenceBytes = streamToArray(istream);
399 // compare the encoder's output to the reference file.
400 compareArrays(encodedBytes, referenceBytes);
402 /* ========== 14 ========== */
403 testnum++;
404 testdesc = "test encoding a scaled ICO with format options " +
405 "(format=bmp;bpp=24)";
407 // we'll reuse the container from the previous test
408 istream = imgTools.encodeScaledImage(container,
409 "image/vnd.microsoft.icon",
410 16,
411 16,
412 "format=bmp;bpp=24");
413 encodedBytes = streamToArray(istream);
415 // Get bytes for exected result
416 refName = "image4gif16x16bmp24bpp.ico";
417 refFile = do_get_file(refName);
418 istream = getFileInputStream(refFile);
419 do_check_eq(istream.available(), 894);
420 referenceBytes = streamToArray(istream);
422 // compare the encoder's output to the reference file.
423 compareArrays(encodedBytes, referenceBytes);
426 /* ========== 15 ========== */
427 testnum++;
428 testdesc = "test cropping a JPG";
430 // 32x32 jpeg, 3494 bytes.
431 imgName = "image2.jpg";
432 inMimeType = "image/jpeg";
433 imgFile = do_get_file(imgName);
435 istream = getFileInputStream(imgFile);
436 do_check_eq(istream.available(), 3494);
438 container = imgTools.decodeImage(istream, inMimeType);
440 // It's not easy to look at the pixel values from JS, so just
441 // check the container's size.
442 do_check_eq(container.width, 32);
443 do_check_eq(container.height, 32);
445 // encode a cropped image
446 istream = imgTools.encodeCroppedImage(container, "image/jpeg", 0, 0, 16, 16);
447 encodedBytes = streamToArray(istream);
449 // Get bytes for exected result
450 refName = "image2jpg16x16cropped.jpg";
451 refFile = do_get_file(refName);
452 istream = getFileInputStream(refFile);
453 do_check_eq(istream.available(), 879);
454 referenceBytes = streamToArray(istream);
456 // compare the encoder's output to the reference file.
457 compareArrays(encodedBytes, referenceBytes);
460 /* ========== 16 ========== */
461 testnum++;
462 testdesc = "test cropping a JPG with an offset";
464 // we'll reuse the container from the previous test
465 istream = imgTools.encodeCroppedImage(container, "image/jpeg", 16, 16, 16, 16);
466 encodedBytes = streamToArray(istream);
468 // Get bytes for exected result
469 refName = "image2jpg16x16cropped2.jpg";
470 refFile = do_get_file(refName);
471 istream = getFileInputStream(refFile);
472 do_check_eq(istream.available(), 878);
473 referenceBytes = streamToArray(istream);
475 // compare the encoder's output to the reference file.
476 compareArrays(encodedBytes, referenceBytes);
479 /* ========== 17 ========== */
480 testnum++;
481 testdesc = "test cropping a JPG without a given height";
483 // we'll reuse the container from the previous test
484 istream = imgTools.encodeCroppedImage(container, "image/jpeg", 0, 0, 16, 0);
485 encodedBytes = streamToArray(istream);
487 // Get bytes for exected result
488 refName = "image2jpg16x32cropped3.jpg";
489 refFile = do_get_file(refName);
490 istream = getFileInputStream(refFile);
491 do_check_eq(istream.available(), 1127);
492 referenceBytes = streamToArray(istream);
494 // compare the encoder's output to the reference file.
495 compareArrays(encodedBytes, referenceBytes);
498 /* ========== 18 ========== */
499 testnum++;
500 testdesc = "test cropping a JPG without a given width";
502 // we'll reuse the container from the previous test
503 istream = imgTools.encodeCroppedImage(container, "image/jpeg", 0, 0, 0, 16);
504 encodedBytes = streamToArray(istream);
506 // Get bytes for exected result
507 refName = "image2jpg32x16cropped4.jpg";
508 refFile = do_get_file(refName);
509 istream = getFileInputStream(refFile);
510 do_check_eq(istream.available(), 1135);
511 referenceBytes = streamToArray(istream);
513 // compare the encoder's output to the reference file.
514 compareArrays(encodedBytes, referenceBytes);
517 /* ========== 19 ========== */
518 testnum++;
519 testdesc = "test cropping a JPG without a given width and height";
521 // we'll reuse the container from the previous test
522 istream = imgTools.encodeCroppedImage(container, "image/jpeg", 0, 0, 0, 0);
523 encodedBytes = streamToArray(istream);
525 // Get bytes for exected result
526 refName = "image2jpg32x32.jpg";
527 refFile = do_get_file(refName);
528 istream = getFileInputStream(refFile);
529 do_check_eq(istream.available(), 1634);
530 referenceBytes = streamToArray(istream);
532 // compare the encoder's output to the reference file.
533 compareArrays(encodedBytes, referenceBytes);
536 /* ========== 20 ========== */
537 testnum++;
538 testdesc = "test scaling a JPG without a given width";
540 // we'll reuse the container from the previous test
541 istream = imgTools.encodeScaledImage(container, "image/jpeg", 0, 16);
542 encodedBytes = streamToArray(istream);
544 // Get bytes for exected result
545 refName = "image2jpg32x16scaled.jpg";
546 refFile = do_get_file(refName);
547 istream = getFileInputStream(refFile);
548 do_check_eq(istream.available(), 1227);
549 referenceBytes = streamToArray(istream);
551 // compare the encoder's output to the reference file.
552 compareArrays(encodedBytes, referenceBytes);
555 /* ========== 21 ========== */
556 testnum++;
557 testdesc = "test scaling a JPG without a given height";
559 // we'll reuse the container from the previous test
560 istream = imgTools.encodeScaledImage(container, "image/jpeg", 16, 0);
561 encodedBytes = streamToArray(istream);
563 // Get bytes for exected result
564 refName = "image2jpg16x32scaled.jpg";
565 refFile = do_get_file(refName);
566 istream = getFileInputStream(refFile);
567 do_check_eq(istream.available(), 1219);
568 referenceBytes = streamToArray(istream);
570 // compare the encoder's output to the reference file.
571 compareArrays(encodedBytes, referenceBytes);
574 /* ========== 22 ========== */
575 testnum++;
576 testdesc = "test scaling a JPG without a given width and height";
578 // we'll reuse the container from the previous test
579 istream = imgTools.encodeScaledImage(container, "image/jpeg", 0, 0);
580 encodedBytes = streamToArray(istream);
582 // Get bytes for exected result
583 refName = "image2jpg32x32.jpg";
584 refFile = do_get_file(refName);
585 istream = getFileInputStream(refFile);
586 do_check_eq(istream.available(), 1634);
587 referenceBytes = streamToArray(istream);
589 // compare the encoder's output to the reference file.
590 compareArrays(encodedBytes, referenceBytes);
593 /* ========== 22 ========== */
594 testnum++;
595 testdesc = "test invalid arguments for cropping";
597 var numErrors = 0;
599 try {
600 // width/height can't be negative
601 imgTools.encodeScaledImage(container, "image/jpeg", -1, -1);
602 } catch (e) { numErrors++; }
604 try {
605 // offsets can't be negative
606 imgTools.encodeCroppedImage(container, "image/jpeg", -1, -1, 16, 16);
607 } catch (e) { numErrors++; }
609 try {
610 // width/height can't be negative
611 imgTools.encodeCroppedImage(container, "image/jpeg", 0, 0, -1, -1);
612 } catch (e) { numErrors++; }
614 try {
615 // out of bounds
616 imgTools.encodeCroppedImage(container, "image/jpeg", 17, 17, 16, 16);
617 } catch (e) { numErrors++; }
619 try {
620 // out of bounds
621 imgTools.encodeCroppedImage(container, "image/jpeg", 0, 0, 33, 33);
622 } catch (e) { numErrors++; }
624 try {
625 // out of bounds
626 imgTools.encodeCroppedImage(container, "image/jpeg", 1, 1, 0, 0);
627 } catch (e) { numErrors++; }
629 do_check_eq(numErrors, 6);
632 /* ========== bug 363986 ========== */
633 testnum = 363986;
634 testdesc = "test PNG and JPEG encoders' Read/ReadSegments methods";
636 var testData =
637 [{preImage: "image3.ico",
638 preImageMimeType: "image/x-icon",
639 refImage: "image3ico16x16.png",
640 refImageMimeType: "image/png"},
641 {preImage: "image1.png",
642 preImageMimeType: "image/png",
643 refImage: "image1png64x64.jpg",
644 refImageMimeType: "image/jpeg"}];
646 for(var i=0; i<testData.length; ++i) {
647 var dict = testData[i];
649 var imgFile = do_get_file(dict["refImage"]);
650 var istream = getFileInputStream(imgFile);
651 var refBytes = streamToArray(istream);
653 imgFile = do_get_file(dict["preImage"]);
654 istream = getFileInputStream(imgFile);
656 var container = imgTools.decodeImage(istream, dict["preImageMimeType"]);
658 istream = imgTools.encodeImage(container, dict["refImageMimeType"]);
660 var sstream = Cc["@mozilla.org/storagestream;1"].
661 createInstance(Ci.nsIStorageStream);
662 sstream.init(4096, 4294967295, null);
663 var ostream = sstream.getOutputStream(0);
664 var bostream = Cc["@mozilla.org/network/buffered-output-stream;1"].
665 createInstance(Ci.nsIBufferedOutputStream);
667 //use a tiny buffer to make sure the image data doesn't fully fit in it
668 bostream.init(ostream, 8);
670 bostream.writeFrom(istream, istream.available());
671 bostream.flush(); bostream.close();
673 var encBytes = streamToArray(sstream.newInputStream(0));
675 compareArrays(refBytes, encBytes);
676 }
679 /* ========== bug 413512 ========== */
680 testnum = 413512;
681 testdesc = "test decoding bad favicon (bug 413512)";
683 imgName = "bug413512.ico";
684 inMimeType = "image/x-icon";
685 imgFile = do_get_file(imgName);
687 istream = getFileInputStream(imgFile);
688 do_check_eq(istream.available(), 17759);
689 var errsrc = "none";
691 try {
692 container = imgTools.decodeImage(istream, inMimeType);
694 // We should never hit this - decodeImage throws an assertion because the
695 // image decoded doesn't have enough frames.
696 try {
697 istream = imgTools.encodeImage(container, "image/png");
698 } catch (e) {
699 err = e;
700 errsrc = "encode";
701 }
702 } catch (e) {
703 err = e;
704 errsrc = "decode";
705 }
707 do_check_eq(errsrc, "decode");
708 checkExpectedError(/NS_ERROR_FAILURE/, err);
711 /* ========== bug 815359 ========== */
712 testnum = 815359;
713 testdesc = "test correct ico hotspots (bug 815359)";
715 imgName = "bug815359.ico";
716 inMimeType = "image/x-icon";
717 imgFile = do_get_file(imgName);
719 istream = getFileInputStream(imgFile);
720 do_check_eq(istream.available(), 4286);
722 container = imgTools.decodeImage(istream, inMimeType);
724 var props = container.QueryInterface(Ci.nsIProperties);
726 do_check_eq(props.get("hotspotX", Ci.nsISupportsPRUint32).data, 10);
727 do_check_eq(props.get("hotspotY", Ci.nsISupportsPRUint32).data, 9);
730 /* ========== end ========== */
732 } catch (e) {
733 throw "FAILED in test #" + testnum + " -- " + testdesc + ": " + e;
734 }
735 };