Add unit tests for query history and remote queries#1166
Conversation
charisk
left a comment
There was a problem hiding this comment.
Thanks for adding some much needed tests!
| this.analysesResults.set(queryId, resultsForQuery); | ||
| void publishResults(resultsForQuery); | ||
| void publishResults([...resultsForQuery]); | ||
| const pos = resultsForQuery.length - 1; |
There was a problem hiding this comment.
Can we rename pos to something more descriptive for the function? e.g. analysisPosition?
Also, just a thought (that should be ignored for this PR!): we could have a better data structure for the query results that deals with stuff like that (replacing an analysis) instead of having to do it here. It'd then make the code a bit more easy to manage.
There was a problem hiding this comment.
I've always like immutable.js for things like this, but I don't like introducing it into an ongoing project. Maybe it's not such a bad idea in this case.
We do need to be careful. Now that we are saving data across restarts, any change in format will cause error when there is an upgrade. It's not a terrible situation since the worst case is that we need to delete some old queries on upgrade.
I should add version number to each saved artifact and the extension can read this and upgrade it appropriately when we change versions.
There was a problem hiding this comment.
I'd be up for using immutable.js or any other way to enforce immutability.
Agree about versions - we'll need to be careful. Perhaps the overall query history store has a version? We can always deal with it the first time we need a new version I think.
| let qhm: QueryHistoryManager; | ||
| let rawQueryHistory: any; | ||
| let remoteQueryResult0: RemoteQueryResult; | ||
| // let remoteQueryResult1: RemoteQueryResult; |
| disposables = new DisposableBucket(); | ||
| rawQueryHistory = fs.readJSONSync(path.join(STORAGE_DIR, 'workspace-query-history.json')); | ||
| remoteQueryResult0 = fs.readJSONSync(path.join(STORAGE_DIR, 'queries', rawQueryHistory[0].queryId, 'query-result.json')); | ||
| // remoteQueryResult1 = fs.readJSONSync(path.join(STORAGE_DIR, 'queries', rawQueryHistory[1].queryId, 'query-result.json')); |
There was a problem hiding this comment.
I'll be writing more tests and will likely need this variable.
There was a problem hiding this comment.
Shall we add it then? Happy either way.
| fs.removeSync(STORAGE_DIR); | ||
| } | ||
|
|
||
| function* walk(dir: string): IterableIterator<string> { |
There was a problem hiding this comment.
Nice! At first I was thinking it might be an overkill to have an a generator for tests, but there's no harm in having it and puts us in a good position if we want to test a lot/big files.
There was a problem hiding this comment.
I should probably move this to a shared location since it might be useful in other places.
|
Putting this into draft mode so I can work on it more. |
b3fa7f6 to
9792a58
Compare
7c1dff9 to
76d6dfa
Compare
| "@types/mocha": "^9.0.0", | ||
| "@types/nanoid": "^3.0.0", | ||
| "@types/node": "^12.14.1", | ||
| "@types/node": "^16.11.25", |
There was a problem hiding this comment.
Need to update to v16 to get the replaceAll method.
| if (cancellationToken !== undefined) { | ||
| cancellationRegistration = cancellationToken.onCancellationRequested(_e => { | ||
| tk(child.pid); | ||
| tk(child.pid || 0); |
There was a problem hiding this comment.
In v16, pid is potentially undefined.
| if (finalSingleItem.status === QueryStatus.Completed) { | ||
| await this._onWillOpenQueryItem.fire(finalSingleItem); | ||
| } |
There was a problem hiding this comment.
Fix small bug to avoid an error when someone clicks on an in progress item.
| @@ -1,11 +0,0 @@ | |||
| /** | |||
There was a problem hiding this comment.
With node 16, this is no longer needed.
| * A simple disposable object that does nothing other than contain a list of disposable objects. | ||
| * This is useful for implementing a `Disposable` that owns other disposable objects. | ||
| */ | ||
| export class DisposableBucket extends DisposableObject { |
There was a problem hiding this comment.
Shall we move this to the tests dir?
ee99427 to
9d17703
Compare
Adds some tests for reading in the history and manipulating. There are some more tests to come later. Maybe in another PR, maybe in this one. Note that this PR uses a new node 16 API String.prototype.replaceAll. I think this is ok since vscode ships with node 16. If this causes problems, I can separate to a different PR and we can discuss there.
9d17703 to
4a928f1
Compare
|
@charisk can you take another look? I've made a lot of changes. |
| * A simple disposable object that does nothing other than contain a list of disposable objects. | ||
| * This is useful for implementing a `Disposable` that owns other disposable objects. | ||
| */ | ||
| export class DisposableBucket extends DisposableObject { |
There was a problem hiding this comment.
Shall we move this to the tests dir?
| "fileSizeInBytes": 81237, | ||
| "downloadLink": { | ||
| "id": "171544171", | ||
| "urlPath": "/repos/dsp-testing/qc-run2/actions/artifacts/171544171", |
There was a problem hiding this comment.
Perhaps shouldn't use dsp-testing testing?
There was a problem hiding this comment.
I can change the repo.
| expect(qhm.treeDataProvider.allHistory.length).to.eq(2); | ||
| }); | ||
|
|
||
| it('should remove and then a query from history', async () => { |
There was a problem hiding this comment.
| it('should remove and then a query from history', async () => { | |
| it('should remove and then add query from history', async () => { |
| ); | ||
| }); | ||
|
|
||
| it('should avoid downloading an analysis result', async () => { |
There was a problem hiding this comment.
| it('should avoid downloading an analysis result', async () => { | |
| it('should avoid re-downloading an analysis result', async () => { |
| }); | ||
| }); | ||
|
|
||
| // Since this test changes the state of the query history manager, we need to copy the original |
There was a problem hiding this comment.
This comment doesn't look like it belongs here exactly - should it be near the test?
| const result1 = arm.getAnalysesResults(rawQueryHistory[1].queryId); | ||
|
|
||
| // Shoule be equal, but not equivalent | ||
| expect(result0).to.deep.eq((arm as any).analysesResults.get(rawQueryHistory[0].queryId)); |
There was a problem hiding this comment.
This looks like it's interrogating the private state of the AnalysisResultsManager which doesn't feel right.
Should we not instead check that what we get back from getAnalysesResults is what we "downloaded"?
There was a problem hiding this comment.
I'm specifically testing here that the results are an equivalent copy of what is stored by the AnalysesResultsManager. Instead of inspecting private state, I could call arm.getAnalysesResults twice and ensure that the objects returned are equivalent but different.
There was a problem hiding this comment.
Ah I see, I think that would make more sense.
There was a problem hiding this comment.
I added these tests because keeping them the same instance created weird race conditions, so just wanted to make sure we don't do this again.
Another reason to use immutable.
| @@ -0,0 +1,21 @@ | |||
| import * as path from 'path'; | |||
There was a problem hiding this comment.
Can I make a suggestion that we start using more specific util modules? e.g. file-utils.ts rather than test-helpers which could be a bucket for pretty much anything.
charisk
left a comment
There was a problem hiding this comment.
Approving since all the comments are actually small suggestions!
- More explicit test helper module names - Fix unit test names - Better sanitization of repo names in tests
|
All comments addressed. |
Adds some tests for reading in the history and manipulating.
There are some more tests to come later. Maybe in another PR, maybe in
this one.
Note that this PR uses a new node 16 API String.prototype.replaceAll.
I think this is ok since vscode ships with node 16. If this causes
problems, I can separate to a different PR and we can discuss there.
Checklist
ready-for-doc-reviewlabel there.