-
-
Notifications
You must be signed in to change notification settings - Fork 676
msglist diffing tests: Fix a flake with stream-subscribed status changing #5415
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
gnprice
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! Comments below.
| // no subscription for stream1 | ||
| // | ||
| // Could spread eg.plusReduxState.subscriptions, for | ||
| // completeness…but then we'd invite flakes where random stream | ||
| // IDs in there sometimes collide with our fixed ones, changing | ||
| // whether a stream is subscribed |
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.
More specifically: it would defeat the "no subscription for stream1", because it might happen to contain a subscription for stream1.
| ]; | ||
|
|
||
| const baseState = eg.reduxStatePlus({ | ||
| streams: [...eg.plusReduxState.streams, stream1, stream2], |
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 could also collide. I'm not sure what the consequences would be -- it might be that the later entry wins, in which case it's a purely latent bug (but a bug because our streams array isn't supposed to have duplicate stream IDs.)
| // Could spread eg.plusReduxState.subscriptions, for completeness…but | ||
| // then we'd invite flakes where random stream IDs in there sometimes | ||
| // collide with our fixed ones, changing whether a stream is subscribed | ||
| eg.makeSubscription({ stream: stream1 }), | ||
| eg.makeSubscription({ stream: stream2 }), |
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 we have any fixed streamIDs here other than those of stream1 and stream2?
I think we don't. That was also the idea of 932c28d , which was to make the streams always subscribed (except in the one test where we specifically want them unsubscribed.)
| state: eg.reduxStatePlus({ | ||
| streams: [...eg.plusReduxState.streams, stream1, stream2], |
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 could be simplified, I think, by starting from baseState rather than use eg.reduxStatePlus directly.
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.
Hmm, now I'm wondering if the other uses of eg.reduxStatePlus in these tests should be switched to start from baseState too. … I guess many of them avoid an issue here by using baseSingleMessage, which has its stream ID fixed at -1. Which is cleverly outside the range that makeStream will ever choose.
The one awkward thing about that situation is that -1 isn't a valid stream ID at all. Possibly a good thing to do here would be for makeStream to never generate a stream ID in some range of small numbers, like never less than 10; and then tests can safely make up constant stream IDs within that range, and never flakily collide. We could do the same for user IDs and message IDs, too.
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 could be simplified, I think, by starting from
baseStaterather than useeg.reduxStatePlusdirectly.
PerAccountState is an opaque type, so we can't write down a literal one in this file, which we'd want to do if making a state that starts from baseState. Is that right?
Hmm, now I'm wondering if the other uses of
eg.reduxStatePlusin these tests should be switched to start frombaseStatetoo.
To do this, we'd need to decide that baseState can serve its current consumers and these new consumers equally well, as both groups of tests evolve. So far, I've felt that the groups are different enough that it's probably not great to tie them together in this way. What do you think?
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.
Possibly a good thing to do here would be for
makeStreamto never generate a stream ID in some range of small numbers, like never less than 10; and then tests can safely make up constant stream IDs within that range, and never flakily collide. We could do the same for user IDs and message IDs, too.
This sounds good; I'll include this in my next revision.
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.
PerAccountStateis an opaque type, so we can't write down a literal one in this file, which we'd want to do if making a state that starts frombaseState.
Hmm yeah, I see.
|
Oh, and here's a comment I apparently didn't submit:
Hmm, yeah. That said: But I think what this flake shows is that there is a good reason to leave out such data: we're making up some constant stream IDs, and the data there may accidentally refer to those. |
|
CI failed. Looks like another iteration of #5404. |
…tests In generateInboundEventEditSequence-test.js, when we build state objects from eg.plusReduxState, the data we add includes some constant message, stream, and user IDs. Constant because they end up appearing in test snapshots, and we want those snapshots to be stable. This is a problem when the data we're building from already claims those IDs, for example, by saying that a stream with ID 1 exists and that we have a subscription for it. Since eg.plusReduxState uses random IDs, this has been happening some small fraction of the time, resulting in flakes where the snapshot says a stream is *not* subscribed, but the input data says it *is*. That's zulip#5415. So, to fix, reserve a small section of stream IDs, including 1 and 2, which we use in the mentioned snapshot tests, so that eg.plusReduxState never chooses them. And similarly reserve a range of message and user IDs, too. As suggested by Greg: zulip#5415 (comment) In another approach to fix those flakes, we might have instead built on eg.plusReduxState by erasing some of it first, removing spreads like the one in streams: [...eg.plusReduxState.streams, stream1, stream2], But as we mentioned in 371e9b4, that'd risk corrupting the state we get from eg.plusReduxState. That's the only example state that claims to offer a realistic uncorrupted state with server data, and it's good not to interfere with that guarantee if we can avoid it. (For example, if eg.plusReduxState grows a reference to a stream in `muteModel`, it'd be corrupt if that stream is absent in the `streams` state.) It's too bad that the easy, natural thing to do is to omit the spreads. Fixes: zulip#5415
After the previous commit, 1 is now in the range `makeStream` won't pick stream IDs from. We originally chose -1 to accomplish that, but it has the downside of not being a realistic, valid stream ID. As suggested by Greg; see zulip#5415 (comment)
14846db to
72419c3
Compare
|
Thanks for the review! Revision pushed, and replies above. |
We'll use this to reserve a few low stream IDs to use as constants in snapshot tests.
…tests In generateInboundEventEditSequence-test.js, when we build state objects from eg.plusReduxState, the data we add includes some constant message, stream, and user IDs. Constant because they end up appearing in test snapshots, and we want those snapshots to be stable. This is a problem when the data we're building from already claims those IDs, for example, by saying that a stream with ID 1 exists and that we have a subscription for it. Since eg.plusReduxState uses random IDs, this has been happening some small fraction of the time, resulting in flakes where the snapshot says a stream is *not* subscribed, but the input data says it *is*. That's zulip#5415. So, to fix, reserve a small section of stream IDs, including 1 and 2, which we use in the mentioned snapshot tests, so that eg.plusReduxState never chooses them. And similarly reserve a range of message and user IDs, too. As suggested by Greg: zulip#5415 (comment) In another approach to fix those flakes, we might have instead built on eg.plusReduxState by erasing some of it first, removing spreads like the one in streams: [...eg.plusReduxState.streams, stream1, stream2], But as we mentioned in 371e9b4, that'd risk corrupting the state we get from eg.plusReduxState. That's the only example state that claims to offer a realistic uncorrupted state with server data, and it's good not to interfere with that guarantee if we can avoid it. (For example, if eg.plusReduxState grows a reference to a stream in `muteModel`, it'd be corrupt if that stream is absent in the `streams` state.) It's too bad that the easy, natural thing to do is to omit the spreads. Fixes: zulip#5415
After the previous commit, 1 is now in the range `makeStream` won't pick stream IDs from. We originally chose -1 to accomplish that, but it has the downside of not being a realistic, valid stream ID. As suggested by Greg; see zulip#5415 (comment)
|
Thanks for the revision! Looks good; merging. |
72419c3 to
ddaf486
Compare
|
Thanks! |
In 371e9b4, we said we preferred spreading
eg.plusReduxState.subscriptions...but I guess at that point we
didn't predict this flake.
See 932c28d for a solution to another flake that involved streams
unstably being subscribed / unsubscribed.
Fixes: #5414