-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Convert more btests to btest_exit. NFC #14415
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
Conversation
04a61db to
8383737
Compare
| self.btest('clientside_vertex_arrays_es3.c', reference='gl_triangle.png', args=['-s', 'FULL_ES3=1', '-s', 'USE_GLFW=3', '-lglfw', '-lGLESv2']) | ||
|
|
||
| def test_emscripten_api(self): | ||
| self.btest('emscripten_api_browser.cpp', '1', args=['-s', 'EXPORTED_FUNCTIONS=_main,_third', '-lSDL']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I may not have the sufficient context yet.. In the existing code, some calls to btest have the expected value of 1, while other have 0 or something else, but the new btest_exit doesn't contain any. Does deleting these different expected values not matter then? Also, some existing test cases report different values depending on tests using REPORT_RESULT, but they are all deleted. These values don't matter and can be deleted safely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btest_exit can detect non-zero exit codes but the default and simplest thing to do is to expect an exit code of zero. What I've done in this change is modified some of the tests to report zero on success and non-zero on failure, at least where it makes sense. As far as I can tell, and this is where you can help me out, I don't think I've modified the semantics of any of the tests. They still report success and failures in the same cases.
For an example of a test where I continue to use the non-zero expectation see test_emscripten_api_infloop which as assert_returncode=7. I can't remember why I didn't change that one in particular, but it shows how btest exit works and how it can be used to assert on non-zero exit codes.
aheejin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, the removal of random return and expected values looks good! Still some more question though:
| assert(ratio == ratio2); | ||
|
|
||
| atexit(never); // should never be called - it is wrong to exit the runtime orderly if we have async calls! | ||
| atexit(check_exit_ok); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous code says this should never be called.. Is this still not supposed to be called? If so it'd be good to make that clear in the comments. If not what changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Previously EXIT_RUNTIME was not set the test would never exit. With btest_exit we set EXIT_RUNTIME so that test does exit, but crucially it should not exit when main returns but when the async works is all done. I will add a comment.
| emscripten_unwind_to_js_event_loop(); | ||
| printf("This should not be called!\n"); | ||
| // Should not reach here | ||
| return 99; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do all these return 99s mean this cannot be reached? Would it be better to make emscripten_unreachable() or something in the test framework?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I think are correct. In some case it means unreachable and something like emscripten_unreachable() would make sense. In other cases we are retuning from main but we want to runtime to continue one and the return value should be ignored. Setting it a non-zero value means that in the case the return value is erronously honored we won't get a false positive test success (exit:0).
| emscripten_cancel_main_loop(); | ||
| exit(x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Including this, there are several places the order of emscripten_cancel_main_loop and exit has changed.. Why is that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously there was no actual exiting of the program so that order of the reporting and the canceling of the loop didn't matter.
Now we want the program to actually exit using exit().. anything that comes after exit is unreachable since exit() will never return. Also exit() won't really exit() if there is still async work going on (such as a main loop) so we need to cancel the loop before calling exit (for a couple of different reasons).
| int main() { | ||
| double devicePixelRatio = emscripten_get_device_pixel_ratio(); | ||
| printf("window.devicePixelRatio = %f.\n", devicePixelRatio); | ||
| assert(devicePixelRatio > 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary? If the assertion fails here the code below becomes moot..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah its kind of redundant, I will simplify.
| #ifdef REPORT_RESULT | ||
| REPORT_RESULT(fetch->status); | ||
| #endif | ||
| assert(fetch->status == 200); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the assertion failure the expected way to fail? Other tests use return 1, so...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assertion failure causes the tests to abort which generates a non-zero return code yes.
| #endif | ||
|
|
||
| pthread_exit(NULL); | ||
| assert(main_loc == child_loc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary? Isn't the return below gonna signal whether the test succeeds or not anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right I will just stick to one or the other.
| REPORT_RESULT(result); | ||
| #endif | ||
|
|
||
| pthread_exit(NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling pthread_exit from main here is just odd.. it might work but it looks pretty out of place. I don't see why it was ever here.
| REPORT_RESULT(result); | ||
| #endif | ||
| } | ||
| assert(result == 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too, is the assertion failure the expected way of failing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we can use assert to fail best_exit tests test these days. (I think that is true of btest too but I can't remember for sure).
| #ifdef REPORT_RESULT | ||
| REPORT_RESULT(result); | ||
| #endif | ||
| exit(result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this result expected to be 0 when the test succeeds? The same question for webgl_timer_query.cpp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One needs to look at the test_browser.py to see what the expected return code of the test is:
def test_webgl_timer_query(self):
...
self.btest_exit('webgl_timer_query.cpp', args=cmd)
In this case we see no special assert_returncode param so the expected result here is zero.
Should I change this to?:
assert(result == 0);
exit(0);
Or maybe:
exit(result == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
There a several different ways we could express it I guess, I'm not sure which is the most clear. Probably the one with the assert?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I quite like the current version because it keeps this change obvious in that it converted REPORT_RESULT(XXX) directly to exit(XXX). Kind of nice one to one mapping and it means the expectation in the python code stays the same.
| emscripten_unwind_to_js_event_loop(); | ||
| printf("This should not be called!\n"); | ||
| // Should not reach here | ||
| return 99; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I think are correct. In some case it means unreachable and something like emscripten_unreachable() would make sense. In other cases we are retuning from main but we want to runtime to continue one and the return value should be ignored. Setting it a non-zero value means that in the case the return value is erronously honored we won't get a false positive test success (exit:0).
| assert(ratio == ratio2); | ||
|
|
||
| atexit(never); // should never be called - it is wrong to exit the runtime orderly if we have async calls! | ||
| atexit(check_exit_ok); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Previously EXIT_RUNTIME was not set the test would never exit. With btest_exit we set EXIT_RUNTIME so that test does exit, but crucially it should not exit when main returns but when the async works is all done. I will add a comment.
| emscripten_cancel_main_loop(); | ||
| exit(x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously there was no actual exiting of the program so that order of the reporting and the canceling of the loop didn't matter.
Now we want the program to actually exit using exit().. anything that comes after exit is unreachable since exit() will never return. Also exit() won't really exit() if there is still async work going on (such as a main loop) so we need to cancel the loop before calling exit (for a couple of different reasons).
| int main() { | ||
| double devicePixelRatio = emscripten_get_device_pixel_ratio(); | ||
| printf("window.devicePixelRatio = %f.\n", devicePixelRatio); | ||
| assert(devicePixelRatio > 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah its kind of redundant, I will simplify.
| #ifdef REPORT_RESULT | ||
| REPORT_RESULT(fetch->status); | ||
| #endif | ||
| assert(fetch->status == 200); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assertion failure causes the tests to abort which generates a non-zero return code yes.
| #endif | ||
|
|
||
| pthread_exit(NULL); | ||
| assert(main_loc == child_loc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right I will just stick to one or the other.
| REPORT_RESULT(result); | ||
| #endif | ||
|
|
||
| pthread_exit(NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling pthread_exit from main here is just odd.. it might work but it looks pretty out of place. I don't see why it was ever here.
| REPORT_RESULT(result); | ||
| #endif | ||
| } | ||
| assert(result == 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we can use assert to fail best_exit tests test these days. (I think that is true of btest too but I can't remember for sure).
| #ifdef REPORT_RESULT | ||
| REPORT_RESULT(result); | ||
| #endif | ||
| exit(result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One needs to look at the test_browser.py to see what the expected return code of the test is:
def test_webgl_timer_query(self):
...
self.btest_exit('webgl_timer_query.cpp', args=cmd)
In this case we see no special assert_returncode param so the expected result here is zero.
Should I change this to?:
assert(result == 0);
exit(0);
Or maybe:
exit(result == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
There a several different ways we could express it I guess, I'm not sure which is the most clear. Probably the one with the assert?
| #ifdef REPORT_RESULT | ||
| REPORT_RESULT(result); | ||
| #endif | ||
| exit(result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I quite like the current version because it keeps this change obvious in that it converted REPORT_RESULT(XXX) directly to exit(XXX). Kind of nice one to one mapping and it means the expectation in the python code stays the same.
There are still many more to convert.. perhaps we should be more systematic about it.
aheejin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation!
There are still many more to convert.. perhaps we should
be more systematic about it. For now I'm just doing them
in batches by hand to keep the reviews of reasonable size.