-
-
Notifications
You must be signed in to change notification settings - Fork 5
test: more accurately simulate a remote note change #3469
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
base: master
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #3469 +/- ##
==========================================
- Coverage 82.20% 82.19% -0.02%
==========================================
Files 611 611
Lines 36433 36468 +35
Branches 6004 6008 +4
==========================================
+ Hits 29951 29975 +24
- Misses 5608 5611 +3
- Partials 874 882 +8 ☔ View full report in Codecov by Sentry. |
1c9bf0f
to
df0bf6b
Compare
src/SIL.XForge.Scripture/ClientApp/src/app/translate/editor/editor.component.spec.ts
Fixed
Show fixed
Hide fixed
df0bf6b
to
25a8930
Compare
A unit test highlighted races, suspected incorrect attempts to simulate remote changes, and seeming data inconsistencies between queries and the documents they query. This unit test problemThe test is described as responding to a remote update, but is applying the update as a local change. editor.component.spec.ts TestEnvironment.resolveNote races a call to noteDoc.submitJson0Op before calling realtimeService.updateQueryAdaptersRemote: noteDoc.submitJson0Op(op => op.set(n => n.status, NoteStatus.Resolved));
this.realtimeService.updateQueryAdaptersRemote(); If we change the winner of the race by modifying the code so that submitJson0Op will finish before updateQueryAdaptersRemote starts, like so noteDoc
.submitJson0Op(op => op.set(n => n.status, NoteStatus.Resolved))
.then(() => {
this.realtimeService.updateQueryAdaptersRemote();
}); then editor.component.spec.ts test 'should remove resolved notes after a remote update' shows a failure, saying
(And it might also be meaningful to modify realtime-doc.ts submit() so the call to adapter.submitOp is awaited rather than raced.) When the test calls noteDoc.submitJson0Op, we get into realtime-query.ts onChange and it changes the count from 5 to 4. But it is a local operation and so does not emit a remote change. The test applies an op locally to resolve a note, but is titled as removing such notes after a remote update. It is not a successful fix to the test to change editor.component.spec.ts resolveNote to specify source as false. If we do this, memory-realtime-remote-store.ts MemoryRealtimeDocAdapter.submitOp does call emitRemoteChange, causing editor.component.ts loadNoteThreadDocs to detect changes from noteThreadQuery (presumably Better simulation of remote changeA helper method now updates both doc data and query results before either are announced. The helper, TestRealtimeService.simulateRemoteChangeJson0Op, seeks to more accurately simulate a remote change during testing. Previously, "remote doc" data was being updated and announced before query results were updated, leading to the application examining outdated query results and failing the test. This PR changes how the remote change simulation is done. Instead of calling noteDoc.submitJson0Op (which races to result in running realtime-query.ts onChange before RealtimeService.updateQueryAdaptersRemote is called), we call test-realtime.service.ts simulateRemoteChangeJson0Op. This helper method updates the doc adapter data, and updates the associated query adapters' docIds, before then emitting doc adapter .changes$ and remoteChanges$ and then query adapter remoteChanges$. When query adapter remoteChanges$ is emitted, that gets into realtime-query.ts onChange where a change is found and RealtimeQuery.remoteChanges$ is emitted. Then in Editor.Component.loadNoteThreadDocs we adjust notes. I can't help but wonder if I have not understood something in our codebase, and that's why I came to this solution. Or maybe I did find a legitimate timing inconsistency that our tests have being doing incorrectly. If so, is my solution in the right place to fix the behaviour? (Question A) Should application code, and test code, assume that RealtimeDocAdapter.data and RealtimeQueryAdapter.docIds are in sync? That is, that neither is up-to-date before the other. And so if RealtimeQueryAdapter.remoteChanges$ fires, you could assume RealtimeDocAdapter.data is up-to-date, and if RealtimeDocAdapter.remoteChanges$ fires, you could assume RealtimeQueryAdapter.docIds is up to date. General problem?I am concerned that this could be a problem in other tests, either (1) incorrectly attempting to simulate remote changes by causing local changes, or (2) assuming query results will be up to date when we respond to doc data changes. We may reveal potential race problems in our software by looking for places where RealtimeDoc.submitJson0Op() (or RealtimeDoc.submit()) is used to simulate a remote change in tests. (And even when submit source is set to false, it's still processed as a local change.) RealtimeQuery.remoteDocChanges$RealtimeQuery.onInsert takes a doc than is newly in the query result set. It subscribes to the doc remoteChanges$. If doc remoteChanges$ emits, RealtimeQuery responds by emitting RealtimeQuery.remoteDocChanges$. However, RealtimeQuery.onChanges might not have been run yet unless a RealtimeQueryAdapter.remoteChanges$ event was handled first. This could mean that RealtimeQuery.docs is not up-to-date when RealtimeQuery announces that a doc has changed. So suppose you have code saying realtimeQueryForMyOwnNotes.remoteDocChanges$.subscribe(() => {
console.log('The data of one of your own notes has changed! Now your own notes are as follows:');
console.log(realtimeQueryForMyOwnNotes.docs)
}); And suppose that a remote change happens that changes someNote.owner = 'someone else'; In response to this,
The realtimeQueryForMyOwnNotes.remoteDocChanges$ event handler would fire, and know that a doc in the query list had a data change. But when it asks the query for the documents ( Am I thinking the right way about this? I see that the TestRealtimeService.simulateRemoteChangesJson0Op method is emitting in the order that should cause the problem, so perhaps that should be adjusted if we keep it. |
This change is