Skip to content

Update test_console_log. NFC. #13088

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 113 additions & 118 deletions tests/emscripten_log/emscripten_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,134 +10,129 @@
#define STRINGIZE_HELPER(x) #x
#define STRINGIZE(x) STRINGIZE_HELPER(x)

int result = 1; // If 1, this test succeeded.
int failed = 0; // If 1, this test failed.

// A custom assert macro to test varargs routing to emscripten_log().
#define MYASSERT(condition, msg, ...) \
do { \
if (!(condition)) { \
emscripten_log(EM_LOG_ERROR, "%s", "Condition '" #condition "' failed in file " __FILE__ ":" STRINGIZE(__LINE__) "!"); \
emscripten_log(EM_LOG_ERROR, msg, ##__VA_ARGS__); \
result = 0; \
} \
} while(0)

void __attribute__((noinline)) kitten()
{
// Log to Emscripten Module.
emscripten_log(EM_LOG_NO_PATHS, "Print a log message: int: %d, string: %s.", 42, "hello");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_WARN, "Print a warning message");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_ERROR, "This is an error!");

// Log directly to Browser web inspector/console.
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE, "Info log to console: int: %d, string: %s", 42, "hello");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_WARN, "Warning message to console.");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_ERROR, "Error message to console! This should appear in red!");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_INFO, "Info message to console.");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_DEBUG, "Debug message to console.");

// Log to with full callstack information (both original C source and JS callstacks):
emscripten_log(EM_LOG_C_STACK | EM_LOG_JS_STACK, "A message with as full call stack information as possible:");

// Log with just mangled JS callstacks:
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_JS_STACK, "This is a message with a mangled JS callstack:");

// Log only clean C callstack:
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_C_STACK, "This message should have a clean C callstack:");
do { \
if (!(condition)) { \
emscripten_log(EM_LOG_ERROR, "%s", "Condition '" #condition "' failed in file " __FILE__ ":" STRINGIZE(__LINE__) "!"); \
emscripten_log(EM_LOG_ERROR, msg, ##__VA_ARGS__); \
failed = 1; \
} \
} while(0)

void __attribute__((noinline)) kitten() {
// Log to Emscripten Module.
emscripten_log(EM_LOG_NO_PATHS, "Print a log message: int: %d, string: %s.", 42, "hello");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_WARN, "Print a warning message");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_ERROR, "This is an error!");

// Log directly to Browser web inspector/console.
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE, "Info log to console: int: %d, string: %s", 42, "hello");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_WARN, "Warning message to console.");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_ERROR, "Error message to console! This should appear in red!");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_INFO, "Info message to console.");
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_DEBUG, "Debug message to console.");

// Log to with full callstack information (both original C source and JS callstacks):
emscripten_log(EM_LOG_C_STACK | EM_LOG_JS_STACK, "A message with as full call stack information as possible:");

// Log with just mangled JS callstacks:
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_JS_STACK, "This is a message with a mangled JS callstack:");

// Log only clean C callstack:
emscripten_log(EM_LOG_NO_PATHS | EM_LOG_C_STACK, "This message should have a clean C callstack:");
}

void __attribute__((noinline)) bar(int = 0, char * = 0, double = 0) // Arbitrary function signature to add some content to callstack.
{
if (1 == 2)
MYASSERT(2 == 1, "World falls apart!");
else
MYASSERT(1 == 1, "");
// Arbitrary function signature to add some content to callstack.
void __attribute__((noinline)) bar(int = 0, char * = 0, double = 0) {
if (1 == 2)
MYASSERT(2 == 1, "World falls apart!");
else
MYASSERT(1 == 1, "");

int flags = EM_LOG_NO_PATHS | EM_LOG_JS_STACK | EM_LOG_FUNC_PARAMS;
int flags = EM_LOG_NO_PATHS | EM_LOG_JS_STACK | EM_LOG_FUNC_PARAMS;
#ifndef RUN_FROM_JS_SHELL
flags |= EM_LOG_C_STACK;
flags |= EM_LOG_C_STACK;
#endif

// We can programmatically get the callstack.
// 1. Ask for callstack length:
int nbytes = emscripten_get_callstack(flags, 0, 0);
// 2. Allocate temp memory to hold the callstack.
char *callstack = new char[nbytes];
// 3. Obtain it.
// 4. Do something with the callstack string.

emscripten_get_callstack(flags, callstack, nbytes);

/* The callstack should be something like
at bar(int, char*, double) (src.cpp.o.js:5383:12)
at void Foo<int>() (src.cpp.o.js:5417:4)
at main() (src.cpp.o.js:5404:2)
at Object.callMain (src.cpp.o.js:71344:30)
at doRun (src.cpp.o.js:71383:25)
at run (src.cpp.o.js:71396:5)
at Object.<anonymous> (src.cpp.o.js:71439:1)
at Module._compile (module.js:456:26)

but the line numbers will greatly vary depending on the mode we are compiling in, so cannot test with direct string comparison. */

if ((flags & EM_LOG_C_STACK) != 0)
{
MYASSERT(!!strstr(callstack, ".cpp:"), "Callstack was %s!", callstack);
}
else
{
MYASSERT(!!strstr(callstack, ".js:"), "Callstack was %s!", callstack);
}
MYASSERT(!!strstr(callstack, "at bar(int, char*, double)"), "Callstack was %s!", callstack);
MYASSERT(!!strstr(callstack, "at void Foo<int>()"), "Callstack was %s!", callstack);

// 5. Clean up.
delete[] callstack;

// Test that obtaining a truncated callstack works. (https://github.com/emscripten-core/emscripten/issues/2171)
char *buffer = new char[21];
buffer[20] = 0x01; // Magic sentinel that should not change its value.
emscripten_get_callstack(EM_LOG_C_STACK | EM_LOG_NO_PATHS | EM_LOG_FUNC_PARAMS, buffer, 20);
MYASSERT(!!strstr(buffer, "at bar(int,"), "Truncated callstack was %s!", buffer);
MYASSERT(buffer[20] == 0x01, "");
delete[] buffer;

// Or alternatively use a fixed-size buffer for the callstack (and get a truncated output if it was too small).
char str[1024];
emscripten_get_callstack(EM_LOG_NO_PATHS | EM_LOG_JS_STACK, str, 1024);

// TODO(sbc): should we try to revive these checks? The callstacks don't look quite like
// this in the wasm world and we already have coverage above I think?
// We can programmatically get the callstack.
// 1. Ask for callstack length:
int nbytes = emscripten_get_callstack(flags, 0, 0);
// 2. Allocate temp memory to hold the callstack.
char *callstack = new char[nbytes];
// 3. Obtain it.
// 4. Do something with the callstack string.

emscripten_get_callstack(flags, callstack, nbytes);

/* The callstack should be something like
at bar(int, char*, double) (src.cpp.o.js:5383:12)
at void Foo<int>() (src.cpp.o.js:5417:4)
at main() (src.cpp.o.js:5404:2)
at Object.callMain (src.cpp.o.js:71344:30)
at doRun (src.cpp.o.js:71383:25)
at run (src.cpp.o.js:71396:5)
at Object.<anonymous> (src.cpp.o.js:71439:1)
at Module._compile (module.js:456:26)

but the line numbers will greatly vary depending on the mode we are compiling in, so cannot test with direct string comparison. */

if ((flags & EM_LOG_C_STACK) != 0) {
MYASSERT(!!strstr(callstack, ".cpp:"), "Callstack was %s!", callstack);
} else {
MYASSERT(!!strstr(callstack, ".js:"), "Callstack was %s!", callstack);
}
MYASSERT(!!strstr(callstack, "at bar(int, char*, double)"), "Callstack was %s!", callstack);
MYASSERT(!!strstr(callstack, "at void Foo<int>()"), "Callstack was %s!", callstack);

// 5. Clean up.
delete[] callstack;

// Test that obtaining a truncated callstack works. (https://github.com/emscripten-core/emscripten/issues/2171)
char *buffer = new char[21];
buffer[20] = 0x01; // Magic sentinel that should not change its value.
emscripten_get_callstack(EM_LOG_C_STACK | EM_LOG_NO_PATHS | EM_LOG_FUNC_PARAMS, buffer, 20);
MYASSERT(!!strstr(buffer, "at bar(int,"), "Truncated callstack was %s!", buffer);
MYASSERT(buffer[20] == 0x01, "");
delete[] buffer;

// Or alternatively use a fixed-size buffer for the callstack (and get a truncated output if it was too small).
char str[1024];
emscripten_get_callstack(EM_LOG_NO_PATHS | EM_LOG_JS_STACK, str, 1024);

// TODO(sbc): should we try to revive these checks? The callstacks don't look quite like
// this in the wasm world and we already have coverage above I think?
#if 0
/* With EM_LOG_JS_STACK, the callstack will be
at __Z3bariPcd (src.cpp.o.js:5394:12)
at __Z3FooIiEvv (src.cpp.o.js:5417:4)
at Object._main (src.cpp.o.js:5404:2)
at Object.callMain (src.cpp.o.js:71344:30)
at doRun (src.cpp.o.js:71383:25)
at run (src.cpp.o.js:71396:5)
at Object.<anonymous> (src.cpp.o.js:71439:1)
at Module._compile (module.js:456:26) */
/* With EM_LOG_JS_STACK, the callstack will be
at __Z3bariPcd (src.cpp.o.js:5394:12)
at __Z3FooIiEvv (src.cpp.o.js:5417:4)
at Object._main (src.cpp.o.js:5404:2)
at Object.callMain (src.cpp.o.js:71344:30)
at doRun (src.cpp.o.js:71383:25)
at run (src.cpp.o.js:71396:5)
at Object.<anonymous> (src.cpp.o.js:71439:1)
at Module._compile (module.js:456:26) */
#ifdef RUN_FROM_JS_SHELL
MYASSERT(!!strstr(str, "at __Z3bariPcd (src.cpp"), "Callstack was %s!", str);
MYASSERT(!!strstr(str, "at __Z3FooIiEvv (src.cpp"), "Callstack was %s!", str);
MYASSERT(!!strstr(str, "at __Z3bariPcd (src.cpp"), "Callstack was %s!", str);
MYASSERT(!!strstr(str, "at __Z3FooIiEvv (src.cpp"), "Callstack was %s!", str);
#else
MYASSERT(!!strstr(str, "at __Z3bariPcd (page.js"), "Callstack was %s!", str);
MYASSERT(!!strstr(str, "at __Z3FooIiEvv (page.js"), "Callstack was %s!", str);
MYASSERT(!!strstr(str, "at __Z3bariPcd (page.js"), "Callstack was %s!", str);
MYASSERT(!!strstr(str, "at __Z3FooIiEvv (page.js"), "Callstack was %s!", str);
#endif
#endif
}

// Arbitrary function signature to add some content to callstack.
template<typename T>
void __attribute__((noinline)) Foo() // Arbitrary function signature to add some content to callstack.
{
bar();
void __attribute__((noinline)) Foo() {
bar();
}

#define TestLog(args...) emscripten_log(EM_LOG_CONSOLE, args)

void PrintDoubleStuff(double first, double second)
{
void PrintDoubleStuff(double first, double second) {
double divided = first / second;

TestLog("%f %f %f\n", first, second, divided);
Expand All @@ -154,19 +149,19 @@ void DoubleTest() {
PrintDoubleStuff(12.3456789, 9.12345678);
}

int main()
{
int test = 123;
emscripten_log(EM_LOG_FUNC_PARAMS | EM_LOG_CONSOLE, "test print %d\n", test);
int main() {
int test = 123;
emscripten_log(EM_LOG_FUNC_PARAMS | EM_LOG_CONSOLE, "test print %d\n", test);

Foo<int>();
Foo<int>();

DoubleTest();

#ifdef REPORT_RESULT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where was this defined? Is it still defined somewhere? Can we get rid of it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I should have given more context.

Traditionally when you run browser test self.btest the test running will inject the report_result.h header (using -include) and expect you to call REPORT_RESULT. However, in recent months I've added self.btest_exit which just relies on the exit code instead. It doesn't inject any headers and it doesn't use this macro. See #12928 and #12977.

REPORT_RESULT(result);
#endif
if (result)
printf("Success!\n");
return 0;
if (failed) {
printf("Failed!\n");
return 1;
}

printf("Success!\n");
return 0;
}
5 changes: 2 additions & 3 deletions tests/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,8 @@ def test_zzz_html_source_map(self):
''')

def test_emscripten_log(self):
src = path_from_root('tests', 'emscripten_log', 'emscripten_log.cpp')
self.compile_btest([src, '--pre-js', path_from_root('src', 'emscripten-source-map.min.js'), '-g4', '-o', 'page.html'])
self.run_browser('page.html', None, '/report_result?1')
self.btest_exit(path_from_root('tests', 'emscripten_log', 'emscripten_log.cpp'), 0,
args=['--pre-js', path_from_root('src', 'emscripten-source-map.min.js'), '-g4'])

def test_preload_file(self):
absolute_src_path = os.path.join(self.get_dir(), 'somefile.txt').replace('\\', '/')
Expand Down