Skip to content

Conversation

@chrisbobbe
Copy link
Contributor

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

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Comments below.

Comment on lines 442 to 447
// 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
Copy link
Member

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],
Copy link
Member

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.)

Comment on lines 201 to 203
// 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 }),
Copy link
Member

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.)

Comment on lines 439 to 438
state: eg.reduxStatePlus({
streams: [...eg.plusReduxState.streams, stream1, stream2],
Copy link
Member

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.

Copy link
Member

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.

Copy link
Contributor Author

@chrisbobbe chrisbobbe Jun 15, 2022

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.

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.reduxStatePlus in these tests should be switched to start from baseState too.

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?

Copy link
Contributor Author

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 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.

This sounds good; I'll include this in my next revision.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Hmm yeah, I see.

@gnprice
Copy link
Member

gnprice commented Jun 14, 2022

Oh, and here's a comment I apparently didn't submit:


In 371e9b4, we said we preferred spreading
eg.plusReduxState.subscriptions...but I guess at that point we
didn't predict this flake.

Hmm, yeah. That said:

msglist tests: Remove some accidental clobbering of `plusReduxState`

On principle; not because there's anything in these particular
fields that we really want. The principle is that we strictly want
to add to the "standard example data" that `plusReduxState` exists
to offer; we have no reason to erase or corrupt it.

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.

@gnprice
Copy link
Member

gnprice commented Jun 14, 2022

CI failed. Looks like another iteration of #5404.

chrisbobbe added a commit to chrisbobbe/zulip-mobile that referenced this pull request Jun 15, 2022
…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
chrisbobbe added a commit to chrisbobbe/zulip-mobile that referenced this pull request Jun 15, 2022
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)
@chrisbobbe chrisbobbe force-pushed the pr-flake-stream-subscribed branch from 14846db to 72419c3 Compare June 15, 2022 18:13
@chrisbobbe
Copy link
Contributor Author

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)
@gnprice
Copy link
Member

gnprice commented Jun 17, 2022

Thanks for the revision! Looks good; merging.

@gnprice gnprice force-pushed the pr-flake-stream-subscribed branch from 72419c3 to ddaf486 Compare June 17, 2022 05:03
@gnprice gnprice closed this in e7cf714 Jun 17, 2022
@gnprice gnprice merged commit ddaf486 into zulip:main Jun 17, 2022
@chrisbobbe
Copy link
Contributor Author

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

msglist-diffing tests: Debug/fix a flake with stream-subscribed status changing

2 participants