testPrintError.cpp (3499B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include <cstdio> // fclose, fflush, open_memstream 9 10 #include "js/ErrorReport.h" // JS::PrintError 11 #include "js/Warnings.h" // JS::SetWarningReporter, JS::WarnUTF8 12 13 #include "jsapi-tests/tests.h" 14 15 class AutoStreamBuffer { 16 char* buffer; 17 size_t size; 18 FILE* fp; 19 20 public: 21 AutoStreamBuffer() { fp = open_memstream(&buffer, &size); } 22 23 ~AutoStreamBuffer() { 24 fclose(fp); 25 free(buffer); 26 } 27 28 FILE* stream() { return fp; } 29 30 bool contains(const char* str) { 31 if (fflush(fp) != 0) { 32 fprintf(stderr, "Error flushing stream\n"); 33 return false; 34 } 35 if (strcmp(buffer, str) != 0) { 36 fprintf(stderr, "Expected |%s|, got |%s|\n", str, buffer); 37 return false; 38 } 39 return true; 40 } 41 }; 42 43 BEGIN_TEST(testPrintError_Works) { 44 AutoStreamBuffer buf; 45 46 CHECK(!execDontReport("throw null;", "testPrintError_Works.js", 3)); 47 48 JS::ExceptionStack exnStack(cx); 49 CHECK(JS::StealPendingExceptionStack(cx, &exnStack)); 50 51 JS::ErrorReportBuilder builder(cx); 52 CHECK(builder.init(cx, exnStack, JS::ErrorReportBuilder::NoSideEffects)); 53 JS::PrintError(buf.stream(), builder, false); 54 55 CHECK(buf.contains("testPrintError_Works.js:3:1 uncaught exception: null\n")); 56 57 return true; 58 } 59 END_TEST(testPrintError_Works) 60 61 BEGIN_TEST(testPrintError_SkipWarning) { 62 JS::SetWarningReporter(cx, warningReporter); 63 CHECK(JS::WarnUTF8(cx, "warning message")); 64 CHECK(warningSuccess); 65 return true; 66 } 67 68 static bool warningSuccess; 69 70 static void warningReporter(JSContext* cx, JSErrorReport* report) { 71 AutoStreamBuffer buf; 72 JS::PrintError(buf.stream(), report, false); 73 warningSuccess = buf.contains(""); 74 } 75 END_TEST(testPrintError_SkipWarning) 76 77 bool cls_testPrintError_SkipWarning::warningSuccess = false; 78 79 BEGIN_TEST(testPrintError_PrintWarning) { 80 JS::SetWarningReporter(cx, warningReporter); 81 CHECK(JS::WarnUTF8(cx, "warning message")); 82 CHECK(warningSuccess); 83 return true; 84 } 85 86 static bool warningSuccess; 87 88 static void warningReporter(JSContext* cx, JSErrorReport* report) { 89 AutoStreamBuffer buf; 90 JS::PrintError(buf.stream(), report, true); 91 warningSuccess = buf.contains("warning: warning message\n"); 92 } 93 END_TEST(testPrintError_PrintWarning) 94 95 bool cls_testPrintError_PrintWarning::warningSuccess = false; 96 97 #define BURRITO "\xF0\x9F\x8C\xAF" 98 99 BEGIN_TEST(testPrintError_UTF16CodeUnits) { 100 AutoStreamBuffer buf; 101 102 static const char utf8code[] = 103 "function f() {\n var x = `\n" BURRITO "`; " BURRITO "; } f();"; 104 105 CHECK(!execDontReport(utf8code, "testPrintError_UTF16CodeUnits.js", 1)); 106 107 JS::ExceptionStack exnStack(cx); 108 CHECK(JS::StealPendingExceptionStack(cx, &exnStack)); 109 110 JS::ErrorReportBuilder builder(cx); 111 CHECK(builder.init(cx, exnStack, JS::ErrorReportBuilder::NoSideEffects)); 112 JS::PrintError(buf.stream(), builder, false); 113 114 CHECK( 115 buf.contains("testPrintError_UTF16CodeUnits.js:3:6 SyntaxError: illegal " 116 "character U+1F32F:\n" 117 "testPrintError_UTF16CodeUnits.js:3:6 " BURRITO "`; " BURRITO 118 "; } f();\n" 119 "testPrintError_UTF16CodeUnits.js:3:6 .....^\n")); 120 121 return true; 122 } 123 END_TEST(testPrintError_UTF16CodeUnits) 124 125 #undef BURRITO