-
Notifications
You must be signed in to change notification settings - Fork 14
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
client: Improve testing and increase coverage #636
Conversation
One of the added tests fails: it is planned to be corrected in the future. Signed-off-by: Leonard Lyubich <[email protected]>
Previously, `Client.Dial` lost causing error of network endpoint parsing. Although the method returned "invalid endpoint options" error, the original reason could not be obtained. This made debugging difficult. Now causes are kept and returned. For this, function `WithNetworkURIAddress` is inlined and the `ParseURI` error is not ignored. Fixes one of the corresponding tests. Signed-off-by: Leonard Lyubich <[email protected]>
fb1e0e2
to
774c74c
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #636 +/- ##
==========================================
+ Coverage 57.47% 58.80% +1.32%
==========================================
Files 164 165 +1
Lines 22503 22751 +248
==========================================
+ Hits 12934 13378 +444
+ Misses 9175 8935 -240
- Partials 394 438 +44 ☔ View full report in Codecov by Sentry. |
11dc379
to
a093108
Compare
oops, |
a093108
to
0df829c
Compare
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.
A number of good fixes.
Regarding embedded gRPC --- it makes testing harder at this level, previously gRPC was layered out and could be tested on its own. I fear we'd get a complete node in tests soon. At the same time we have to handle gRPC somewhere anyway and going through the whole cycle can be beneficial. Take httptest
for example, it's an HTTP server and many APIs are tested against it (like NeoGo's JSON-RPC). gRPC is not much different here.
defer func() { | ||
c.sendStatistic(stat.MethodBalanceGet, err)() | ||
}() | ||
if c.prm.statisticCallback != nil { |
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.
Likely you can just defer c.sendStatistic(...)()
and handle statisticCallback
and startTime
internally.
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.
if if
is inevitable, then it is better to make a conditional defer
imo
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.
but why? you turned out the func that is commonly used and made more lines, no? i think it was planned as defer c.sendStatistic(...)()
but smth went wrong, why make things harder?
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.
Not doing a defer
is obviously more efficient, but for these (network) operations the difference is so negligible that I'd rather opt for simpler code.
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've done this not just for negligible optimization but for more clear code. Previously, i saw unconditional deferred stats, making me think that some stats are always tracked while sendStatistics
encapsulates the logic that there can be no stats at all! Also, seeing defer func() { c.method()() }()
blows my mind, i definitely cannot agree this is a simpler code
finally, if no one has any categorical objections, i'd leave the fixed version
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.
any categorical objections
mine is many repetitive lines for every method. also, you still use defer
so why not, at least i would try to inline time calculation: time.Since(time.Now())
seeing defer func() { c.method()() }() blows my mind
agree but once you get it you just see in every method, it is our general approach
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.
at least i would try to inline time calculation:
time.Since(time.Now())
hm, how would it be?
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 meant start time can be an arg of the deferred func, provided wrong example
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.
done
yeah, tests will definitely become harder todo, but the closer test code is to the real execution, the better it works in error and regression control. I want to be able to track problems at all transmission levels i also believe that after all tests will be ready, future support wont be so hard todo
to some extent it will be so, and I think it is inevitable. For example, u wanna test that the sent request is correctly signed. To do this, u still have to intercept and check it. Then u wanna check that the client will return a certain result to the user for a certain server response. So, the abstraction interface should work with both requests and responses, as it does in the proposed version. That means that regardless of whether gRPC layer is abstracted or not, test implementations will be almost the same. That's why i included it into the test framework u can also see some gRPC code we used has already become deprecated. To make sure our future upgrade passed purely and compatible, we should not abstract this level |
The function is placed inside the lib to facilitate its support and as a preliminary preparation for the obsolescence of `github.com/nspcc-dev/neofs-api-go/v2` module. Refs #381. Signed-off-by: Leonard Lyubich <[email protected]>
The function return zeros on multiaddr input. Signed-off-by: Leonard Lyubich <[email protected]>
Previously, `Client.Dial` method sometimes tried to connect to obviously invalid addresses (e.g. with missing port). although a preliminary endpoint check is performed, some errors were ignored, and they still popped up during the subsequent dial. Thus, in general the client's behavior was correct and the expected error was still caught. Thus, in general, the client's behavior was correct and the error was still caught, however, unnecessary obviously failed actions were made, which could be cut off at the pre-check stage. Now the `util.ParseURI` function has been improved and catches most cases. Test endpoints are corrected for `pool.Pool`. Signed-off-by: Leonard Lyubich <[email protected]>
There is no any point to have them different. Signed-off-by: Leonard Lyubich <[email protected]>
Nil response without an error can lead to the undesired behavior. Since other methods are not expected to be called, unimplemented error fits the best. Signed-off-by: Leonard Lyubich <[email protected]>
There is already an interface for this. Also, changing global variables is always weird. Signed-off-by: Leonard Lyubich <[email protected]>
For two operations it has already been properly done, and for the rest for some reason through global variables. This also returns skipped tests to action: in approach with interfaces any method can be overridden. Signed-off-by: Leonard Lyubich <[email protected]>
One step closer to github.com/nspcc-dev/neofs-api-go/v2 module deprecation. Previously, for the `Client`, network connecting, sending a request and receiving a response was almost completely hidden in the lib. Now the code is built into the client itself. The test framework used to be too abstract and far from the production version. Although the gRPC lib is vendored, it covers most of the `Client` mechanics. In fact, proper testing requires emulating the behavior of the client-server communication as realistically as possible. This reworks the tests by abstracting only the network transport via in-memory buffer implementation supplied by gRPC lib itself. From now unit tests should provide protocol-declared RPC handlers exactly like NeoFS storage nodes does. This automatically includes gRPC layer to testing, making the client implementation more resilient to corresponding module updates. Signed-off-by: Leonard Lyubich <[email protected]>
Signed-off-by: Leonard Lyubich <[email protected]>
Mainly checks the correctness and integrity of messages sent over the network To be continued: other methods will be covered by similar tests in the future. Signed-off-by: Leonard Lyubich <[email protected]>
Previous name 'missing' could be misinterpreted: missing what? Signed-off-by: Leonard Lyubich <[email protected]>
There is no point in keeping this test separate from the others, so merged. Signed-off-by: Leonard Lyubich <[email protected]>
It speaks the truth, but it's not that easy to fix. Signed-off-by: Leonard Lyubich <[email protected]>
Previously, an incorrect duration was passed to the statistics handler of all operations. Deferred function sent the time elapsed from the start point to the almost instant calculation of the closure arguments (nanoseconds). Now client correctly measures the execution time. Also, as a slight improvement, these actions are deferred conditionally now. Signed-off-by: Leonard Lyubich <[email protected]>
0df829c
to
195a8f2
Compare
grpc.Conn
directly