Simplify output handling in unit tests#494
Conversation
✅ Deploy Preview for splinterdb canceled.
|
218ce4c to
85fdae2
Compare
rtjohnso
left a comment
There was a problem hiding this comment.
I generally prefer command-line args over environment variables, but env vars are fine if there's a technical challenge to implementing this as a command-line arg.
| INCLUDE_SLOW_TESTS: #@ str(not quick).lower() | ||
| RUN_NIGHTLY_TESTS: #@ str(test_nightly).lower() | ||
| BUILD_VERBOSE: "1" | ||
| VERBOSE: "1" |
There was a problem hiding this comment.
Any reason to make this an environment variable instead of a command-line option?
There was a problem hiding this comment.
Yeah, a flag would be preferable for ease of typing and for discoverability. I just couldn't figure out how to make it work: the interactions between unit/main.c, config.h, unit/config_parse_test.c, and unit/splinter_test.c were just too messy for me to untangle in the couple hours that I spent on this. I'd welcome some help on that from @gapisback or anyone else.
There was a problem hiding this comment.
+1, that would be ideal, but I can see why that would be tricky. Future work.
There was a problem hiding this comment.
@rosenhouse -- I'll need to think this through with you. Am looking at the diffs now and pondered over how to achieve what you want.
Some time ago, I had added this --verbose-progress option that was used initially in functional/splinter_test.c to do some verbose progress reporting while large test workloads run. This arg is parsed and tracked as a bool in test_exec_config->verbose_progress.
With some work we could co-opt this flag to also mean what this VERBOSE=1 env-var wants to do. This boolean field may be the replacement for your newly-added Ctest_verbosity flag.
I'm not entirely sure that this scheme will work to meet all the requirements this change-set is bringing-in. (For instance, the functional tests still seem to spit out messages to stdout even when VERBOSE is not set. I'm a bit confused as to what the expected design is with regards to outputs from tests with this and your previous commit at SHA d2e9e86.)
If there is not a great hurry to replace the new env-var with a command line arg, my suggestion is to let this change set go in as-is. And you & I can talk off-line to see how to smooth things over in future editions.
There was a problem hiding this comment.
Yes, we'll return to this in future work
| // and platform_error_log() messages go to stderr. | ||
| // | ||
| // Use platform_set_log_streams() to send the log messages elsewhere. | ||
| typedef FILE platform_log_handle; |
There was a problem hiding this comment.
Excellent idea to remove these from the public api.
| INCLUDE_SLOW_TESTS: #@ str(not quick).lower() | ||
| RUN_NIGHTLY_TESTS: #@ str(test_nightly).lower() | ||
| BUILD_VERBOSE: "1" | ||
| VERBOSE: "1" |
There was a problem hiding this comment.
+1, that would be ideal, but I can see why that would be tricky. Future work.
| // and platform_error_log() messages go to stderr. | ||
| // | ||
| // Use platform_set_log_streams() to send the log messages elsewhere. | ||
| typedef FILE platform_log_handle; |
85fdae2 to
520edca
Compare
| CTEST_ERR("invalid ranges in original tree\n"); | ||
| } | ||
|
|
||
| /* platform_default_log("\n\n\n"); */ |
There was a problem hiding this comment.
I'm not so sure about deleting this dead code and the old lines on L249 onwards below.
Seems like the code author had felt a need that this kind of debugging would be handy if ever this one had to troubleshoot failures in this test's execution.
I'm generally tolerant about such code being left behind, as it does help some future engineer who might have to debug this stuff. (Rob didn't complain, surprisingly ... as he's the author.)
What if we (a) either retain this dead-code in comments or (b) enclose it under if (FALSE) { }? The code is there for troubleshooting and doesn't get in anyone's way.
There was a problem hiding this comment.
I strongly dislike dead code. I'm going to delete it. No one is speaking up to claim this code as theirs, and I'm guessing it could be added back by someone who's making changes.
| fprintf(stdout, __VA_ARGS__); \ | ||
| fflush(stdout); \ | ||
| } \ | ||
| } while (0) |
There was a problem hiding this comment.
Minor suggestion. It is sufficient if you code this multi-line macro simply as:
if (Ctest_verbosity) { ...} else
Missing ; at end of else will take care of correct usage.
There was a problem hiding this comment.
That seems dangerous to me.
Suppose someone forgets the ; and writes
CTEST_LOG_INFO("foo")
something_important();With the do/while implementation of the macro, the compiler will error:
tests/unit/splinterdb_quick_test.c:862:25: fatal error: expected ';' after do/while statement
CTEST_LOG_INFO("foo")
^
;
But with your proposed if/else implementation, it compiles cleanly, and then something_important() only gets called when VERBOSE is unset.
tests/unit/main.c
Outdated
| typedef int (*ctest_filter_func)(struct ctest *); | ||
|
|
||
| // If 0, then CTEST_LOG_INFO() and CTEST_LOG() will no-op. Defaults to 0. | ||
| int Ctest_verbosity = 0; |
There was a problem hiding this comment.
Any reason why this is declared as int rather than as bool ? (I think I dimly recall some issue with using bool as a type in ctests' main.c ... Maybe that's why this is an int ?)
You may want to doc that this is really being treated as a boolean variable.
It would be good to be consistent elsewhere where this variable is checked. In some places code does if (Ctest_verbosity) and in others it does if (Ctest_verbosity > 0).
There was a problem hiding this comment.
Examples:
tests/unit/limitations_test.c-73- if (Ctest_verbosity) {
v/s
tests/unit/splinterdb_quick_test.c-101- if (Ctest_verbosity > 0) {
tests/unit/splinterdb_stress_test.c-51- if (Ctest_verbosity > 0) {
There was a problem hiding this comment.
Good point. Changed to _Bool on latest.
| uint32 num_rounds = 5; | ||
| for (uint32 round = 0; round < num_rounds; round++) { | ||
| platform_default_log("range delete round %d...\n", round); | ||
| CTEST_LOG_INFO("range delete round %d...\n", round); |
There was a problem hiding this comment.
My comment is not specifically tied to this diff, or the diff below on L164.
I just wondered ... how would a new test author know which interface to use for printing messages.
Unit-tests: I noticed that in splinter_test.c, we are still using platform_default_log(), while in other files we are using CTEST_LOG_INFO().
Functional-tests: are all using platform_default_log().
I am wondering ... how can we provide guidelines on what to use where. May be a README in tests/ sub-dir with some general guidelines on what to use where (platform_default_log(), CTEST_LOG_INFO() and CTEST_ERR()) will be helpful. I will certainly forget these details and will benefit from archived how-to instructions for future reference.
There was a problem hiding this comment.
Yes, that was a problem before this PR (multiple ways to print between tests). I think splinter_test.c is a special case, because it is testing private APIs. That said, based on this feedback, I've made the following updates to this file in the most recent commit:
- updated this file to use the
CTEST_LOG_INFO()macro as much as I could easily... though there are other places where it uses private APIs to print to thePlatform_default_log_streamand I'm not going to touch that in this PR. - Made it respect the verbose flag by calling
platform_set_log_streams()the right way - added a note to the top of this file to warn folks not to follow patterns here.
| pthread_t thread_id = pthread_self(); | ||
|
|
||
| fprintf(stderr, "Writing lots of data from thread %lu\n", thread_id); | ||
| CTEST_LOG_INFO("Writing lots of data from thread %lu\n", thread_id); |
There was a problem hiding this comment.
This and the diff on L179 is a good catch. Thanks!
gapisback
left a comment
There was a problem hiding this comment.
Hi, @rosenhouse - Thanks for taking an issue off my plate and improving the usage landscape somewhat!
I have marked-up minor comments and suggestions; nothing major, so assume that you will be able to address them accordingly.
A general comment is that it will be a bit confusing for a new test-code author to figure out which interface to use where, functional and unit tests code. (I myself will forget and will end up searching what we did in other tests and copy from there.)
I suspect there will be a bit more churn in this area, especially relating to interface and handling of (current) env-var VERBOSE and / or --verbose-progress argument.
I think it will be helpful to having coding-level guidelines perhaps, in testing.md or in unit_testing.md.
We can develop this off-line once the dust settles on this area.
- Unit tests respect VERBOSE environment variable,
which ensures output goes to stdout/stderr.
- When VERBOSE is unset, or set to "0" or "false", then:
- stdout will show only 1 status line per test
- stderr will be silent, except for error messages
- When VERBOSE is set to any other value, then
library and unit test info messages go to stdout.
- When a unit test fails, the user will see a suggestion
to set VERBOSE=1 to see all the detailed output.
(TODO: the suggestion doesn't appear on a crash, but that'd be nice)
- Library log lines from unit tests no longer go to /tmp/unit_test.std[out,err]
- Platform_default_log_handle and Platform_error_log_handle are no
longer part of the public API surface. Applications (and tests
that mimic apps) must use platform_set_log_streams() instead.
- Cleans up some tests to avoid a direct dependency on platform.h:
- Removes some references to Platform_*_log_handle globals
and instead calls platform_set_log_streams()
- Removes some calls to platform_default_log()
and instead use a dedicated CTEST_LOG_INFO() macro.
- This isn't complete, but is a start
- Enable VERBOSE mode when running tests in CI
520edca to
5d3e224
Compare
|
@gapisback Thanks for the review. I've tried to improve the "new test author experience" part by updating And yes, let's merge this as-is, and we'll defer the flag thing to later. |
Unit tests respect a new
VERBOSEenvironment variable, which ensures output goes tostdout/stderr.When
VERBOSEis unset, or set to0orfalse, then:stdoutwill show only 1 status line per teststderrwill be silent, except for error messagesWhen
VERBOSEis set to any other value, then library and unit test info messages go tostdout.When a unit test fails, the user will see a suggestion to set
VERBOSE=1to see all the detailed output.(TODO: the suggestion doesn't appear on a crash, but that'd be nice)
Library log lines from unit tests no longer go to
/tmp/unit_test.std[out,err]Platform_default_log_handleandPlatform_error_log_handleare no longer part of the public API surface. Applications (and tests that mimic apps) must useplatform_set_log_streams()instead (see Enable application to silence info logs #487)Cleans up some tests to avoid a direct dependency on
platform.h:Platform_*_log_handleglobals and instead calls newplatform_set_log_streams()platform_default_log()and instead use a dedicatedCTEST_LOG_INFO()macro.Fixes #288
Here's a side-by-side comparison, running in quiet mode (default) on the left, and with

VERBOSE=1on the right.and here's what it looks like when a test fails and you haven't set VERBOSE yet:
