-
Notifications
You must be signed in to change notification settings - Fork 166
Rigorously specify and test pipeTo #512
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
This will help with specifying pipeTo, as seen in #512. This also aligns the spec, tests, and reference implementation on sharing a single error object across both closed and ready promises; previously this was untested and the reference implementation did so but the spec did not.
This will help with specifying pipeTo, as seen in #512. This also aligns the spec, tests, and reference implementation on sharing a single error object across both closed and ready promises; previously this was untested and the reference implementation did so but the spec did not.
8d972ed
to
3ad0eeb
Compare
I like this style. I find it easy to read and easy to write tests for. |
This will help with specifying pipeTo, as seen in #512. This also aligns the spec, tests, and reference implementation on sharing a single error object across both closed and ready promises; previously this was untested and the reference implementation did so but the spec did not.
3ad0eeb
to
f8ae6ef
Compare
new *TypeError*. | ||
* <i>Cleanup</i>: if any of the above requirements ask to perform cleanup, then: | ||
* Wait until any outstanding reads or writes finish (i.e. the corresponding promises settle). If that causes one | ||
of the above error conditions to be true, jump back to those requirements instead of proceeding with cleanup. |
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.
Depending on resolution of #476, we might need to mention the error situation where write() promise rejects but the destination writable stream doesn't get errored.
|
Update: I made a lot of progress on this today. In the process I discovered some contradictions in the spec text as written, which was kind of expected. E.g. races between the various error conditions, or races between performing cleanup (now renamed shutdown) and finishing a write. The spec has been amended, and also the reference implementation has been rewritten to follow the spec. There are still a number of failing (unconverted) tests, so I guess the algorithm is probably not quite right yet. I was still not able to remove many existing tests because we have a lot of good tests that manage to put a stream in a given state asynchronously, possibly after some chunks have already passed through it. Whereas the new tests I've written so far all put the stream in a given state synchronously or use a rejected promise returned from the start() function. I am not sure yet whether I want to solve this in some kind of generative way (maybe like the templated tests) or just by porting the existing ones individually. I'll try to work on it tomorrow. |
This will help with specifying pipeTo, as seen in #512. This also aligns the spec, tests, and reference implementation on sharing a single error object across both closed and ready promises; previously this was untested and the reference implementation did so but the spec did not.
This will help with specifying pipeTo, as seen in #512. This also aligns the spec, tests, and reference implementation on sharing a single error object across both closed and ready promises; previously this was untested and the reference implementation did so but the spec did not.
f7767a7
to
5696093
Compare
In the process of testing this, ported several tests to web-platform-tests format, and introduced the recording stream helpers that I am using extensively in #512.
5696093
to
798a7b6
Compare
This is allllmost done. Some TODOs listed in the commit message, all minor. Last time I said "tomorrow" in this thread that didn't work out, but I'm hopeful... |
@@ -0,0 +1,43 @@ | |||
'use strict'; | |||
|
|||
self.getterRejects = (t, obj, getterName, target) => { |
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 would prefer assertGetterRejects(), to make it clear that this is an assertion.
I thought about assert_getter_rejects(), but then people might expect to find the definition in testharness.js.
I realise that testharness's "promise_rejects" doesn't include "assert", but I find that a bit counter-intuitive to be honest.
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.
This whole file already exists upstream; I just am copying it here because of limitations of the test runner.
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. Never mind then.
798a7b6
to
42fa349
Compare
This is done and ready for review! |
42fa349
to
1f32890
Compare
In the process of testing this, ported several tests to web-platform-tests format, and introduced the recording stream helpers that I am using extensively in #512.
1f32890
to
119449f
Compare
It could. I find the spec and reference implementation cleaner this way.
Added some bullet points
Hmm. Given that only one flag can be used in any given pipeTo, I'm not sure how valuable this would be. Could you give an example of what you'd be hoping to test? Although, I guess I just realized we do not have any tests for multiple close/error conditions being true at once :(. So e.g. piping a closed readable stream to an errored writable stream and so on. The spec isn't even super clear about what takes precedence there. I guess that's another reasonably large chunk of work to do. I'll try to do it Monday. |
E.g. please try simply adding That's the background of my comment at #512 (comment). In general, I think it's worth testing some cases where two or three of prevent.* flags are set to a truthy value (though no need to have full coverage) as it's possible and should be common to do so, in addition to what you've done which is, of course, needed and important.
Agreed. |
Why? The entire setup is designed specifically so that it's harmless and doesn't affect public behavior; we shouldn't need to do any extra bookkeeping for suppression. |
Okay. I still think we should have the if-clause and some tests with multiple prevent.* set to true, but it shouldn't block this from landing. lgtm. I'll open an issue for that. |
Created. Let's discuss this there. |
lgtm based on my own superficial review and tyoshino's in-depth lgtm. |
b7f5663
to
f65451f
Compare
I have to leave early today unfortunately. I want to get some good tests for multiple error/closure scenarios before merging this. So I've pushed up some WIP ones that are mostly failing. The tests might be bad or the spec or the logic; not sure yet. No need to pay them much attention unless you have extra free time. Just wanted to give an update. I think we can also resolve #557 before merging this too. |
This commit introduces an actual spec for pipeTo, now that writable streams are nailed down. The algorithm explicitly notes that much of the actual data movement is unobservable due to locking, and as such just specifies some requirements (mostly around error and close propagation) for how the piping must happen. The reference implementation pipeTo is rewritten to more explicitly reflect this algorithm and its requirements. All pipeTo tests have been converted to web platform tests format, with cleanups as that was done. Some coverage was lost by not using the templating machinery, but some was gained by testing the options more exhaustively in various scenarios. One flow control test (the complicated one with the many different times at which things are tested) changed in expectation, in a positive way. We now explicitly prohibit reading while the writable stream is not ready, whereas the previous algorithm would read a chunk from the readable stream and keep it in "limbo" between the two streams. The new formulation propagates backpressure better; the readable stream's queue is not alleviated prematurely, so backpressure propagates more reliably.
This avoids an extra "wait until any ongoing writes finish".
…seWithErrorPropagation
f65451f
to
b363d00
Compare
b363d00
to
ad3aaaf
Compare
This is a first draft at the "algorithm" for pipeTo, which contains a few concrete steps and a lot of more general requirements. I'd love feedback on whether this style of speccing is clear enough, or if I missed any important requirements, or if the way in which I grouped the requirements is confusing, or anything else. I'm kind of nervous about this part :)
Preview at https://streams.spec.whatwg.org/branch-snapshots/spec-pipe-to-omg/#rs-pipe-to
Things to do before this is merge ready:
Factor this out into a StreamPipe() abstract op that other specs could use. (ReadableStreamPipe??)Let's wait until we have consumers first