Skip to content
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

phpunit tests converted to mocha/chai #140

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

abaevbog
Copy link
Contributor

Addresses Issue #138

v1 and v2 tests that do not require s3 integrations.

@abaevbog abaevbog requested a review from dstillman May 19, 2023 03:46
@abaevbog abaevbog self-assigned this May 19, 2023
Copy link
Member

Choose a reason for hiding this comment

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

sync1download.xml and sync2upload.xml can be removed. These were from the old sync system.

json.prefix + fileContents + json.suffix,
{ "Content-Type": json.contentType }
);
Helpers.assert201(response);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dstillman
This call fails with a complaint that the size does not match what was proposed.
The general issue is that there seems to be a different number of bytes in a file vs its stringified representation that is put into the body of post requests.
I worked around this by using the bytes of an already stringified buffer before getting authorization and then doing the upload - see return values from generateZip function as an example.
Here, though, md5 and zipMD5 are hardcoded on the actual dataserver so when I tried to use bytes of stringified file content, I got an error during authorization "Specified file size incorrect for known file"

assert.equal(contentType, json.contentType);
assert.equal(charset, json.charset);
const updated = Helpers.xpathEval(xml, '/atom:entry/atom:updated');
assert.notEqual(serverDateModified, updated);
Copy link
Contributor Author

@abaevbog abaevbog May 26, 2023

Choose a reason for hiding this comment

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

This line fails. In phpunit test, this condition "should" always fail as well.

There seems to be an error with xpath in phpunit on this line: $serverDateModified = array_get_first($xml->xpath('/atom:entry/atom:updated'));. It makes serverDateModified always null, so on this line, $this->assertNotEquals($serverDateModified, array_get_first($xml->xpath('/atom:entry/atom:updated'))); always passes because one of the values is null.

Fixing the xpath in phpunit for //atom:entry/atom:updated makes serverDateModified not null but then it is the same as updated value fetched from the xml, so the assertion fails.

So this assertion fails, just like it should in phpunit. I notice this condition was removed in V3. Should we remove it here as well?

Copy link
Member

@dstillman dstillman left a comment

Choose a reason for hiding this comment

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

Still going through this, but some initial comments

const fs = require("fs");
const wgxpath = require('wgxpath');

class API3 extends API2 {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we want to extend here. v3 is the default version, and we could deprecate older versions at any time (we haven't in a decade or more, but we could…), so it doesn't make sense to make this dependent on an older version. If different versions need different helpers, they should just be separate files with some duplicate code, and we ideally never touch the older ones again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, I did the extension to avoid duplicate code at first but since it is not an issue, I made independent api2/3 and helpers2/3 that have some functions overlapping

},
"scripts": {
"test": "mocha \"test/**/*.js\"",
"test_file": "mocha \"test/3/publicationTest.js\""
Copy link
Member

Choose a reason for hiding this comment

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

I assume this was just for development?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, shouldn't have committed it in the first place. I'll get rid of this

@@ -0,0 +1,35 @@
{
"verbose": 1,
"syncURLPrefix": "http://dataserver/",
Copy link
Member

Choose a reason for hiding this comment

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

Don't need this

config = JSON.parse(data);
config.timeout = 60000;
config.numOwnedGroups = 3;
config.numPublicGroups = 2;
Copy link
Member

Choose a reason for hiding this comment

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

What's the logic for why these are in here and not in config.json?

In any case, we should use the npm config package and move everything into a default.json5 file in config (like translation-server).

And then we could either do a find-and-replace to switch to the recommended access method or we could just stick to direct property access. get() would let us set values (e.g., rootUsername/rootPassword) to undefined in default.json to force them to be populated in a local.json, but since these are tests anyway, they'll just fail if something isn't configured properly, so maybe it's not worth the extra noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nothing specific here. I think the config.ini used in phpunit did not have those fields, and they were set in some of the other php files. I was converting files one by one, so it just turned out that way.
Anyways, after my cleanup, I removed it all and setup the node-config with default.json5

"awsAccessKey": "",
"awsSecretKey": "",
"filesystemStorage": 1,
"syncVersion": 9,
Copy link
Member

Choose a reason for hiding this comment

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

Don't need this


static async resetSchemaVersion() {
const schema = JSON.parse(fs.readFileSync("../../htdocs/zotero-schema/schema.json"));
this.schemaVersion = schema;
Copy link
Member

Choose a reason for hiding this comment

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

This appears to be storing the entire file, not the schema version.

const crypto = require('crypto');
const fs = require('fs');

class Helpers3 extends Helpers {
Copy link
Member

Choose a reason for hiding this comment

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

Same here as API3.

{
"dependencies": {
"@aws-sdk/client-s3": "^3.338.0",
"axios": "^1.4.0",
Copy link
Member

Choose a reason for hiding this comment

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

Axios is gone, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, sorry. I just didn't push package.json until just now

if (error.name === 'FetchError') {
console.log('Request aborted. Wait for 2 seconds and retry...');
await new Promise(r => setTimeout(r, 2000));
tried += 1;
Copy link
Member

Choose a reason for hiding this comment

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

What was the deal with this? Clients should obviously retry requests automatically, but that's not really something we want in our tests, since it shouldn't be necessary and could hide actual problems. Can we just fix whatever the server problem is that led to this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I've been having the issue with the socket hanging up every now and then when I run test files. Happened randomly on different tests.
This issue never happened with php-unit, so I wasn't sure what to think. I added this wrapper to be able to continue working on tests without getting stuck on figuring out the dataserver configuration.

Now that the tests are virtually done, I will dig into apache config on the zotero-dataserver. It must be something from there

},
API1WrapUp: async () => {
await API.userClear(config.userID);
},
Copy link
Member

Choose a reason for hiding this comment

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

Let's use Before and After like Mocha, SetUp and TearDown like PHPUnit, Start/Stop, Start/Shutdown, or something else consistent and distinct.

(Setup is a noun, so would need to be SetUp to be consistent, but SetUp and WrapUp are a bit too similar.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I renamed them for API#Before and API#After

@abaevbog abaevbog changed the title phpunit test v1 and v2 converted to mocha/chai phpunit tests converted to mocha/chai May 31, 2023
if (!success) {
throw new Error(`${method} to ${url} did not succeed after ${attempts} attempts.`);
}
await new Promise(resolve => setTimeout(resolve, 0));
Copy link
Member

@dstillman dstillman May 31, 2023

Choose a reason for hiding this comment

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

You should add a comment with a link to the GitHub issue so we can track that bug.

Copy link
Member

Choose a reason for hiding this comment

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

I just meant to comment the line so we know why this is here, not to add a comment on GitHub.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it! My bad

Copy link
Member

Choose a reason for hiding this comment

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

I mean literally add a comment to the source code above this line and commit it. Nothing to do with our GitHub. There just shouldn’t be random unexplained lines in the source code that will stay there forever because we don’t know why they’re there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Understood. Sorry about that

// due to bug in node-fetch: https://github.com/node-fetch/node-fetch/issues/1735
const httpAgent = new http.Agent({ keepAlive: true });
const httpsAgent = new https.Agent({ keepAlive: true });
const agentSelector = function (_parsedURL) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Despite adding a tiny delay before each API call, the socket hanging happened again tonight as I was running tests. I added http agents with keepalive=true as another workaround suggested in the issue. Seems to be helping but I will keep track on this. Thinking to try out axios just so see if it would help

@abaevbog
Copy link
Contributor Author

abaevbog commented Jun 1, 2023

I was wrong to blame node-fetch bug for the socket hanging issue. I re-wrote httpHandler with node:http instead of node-fetch, and the same issue remained. Then, I finally managed to reproduce the issue with phpunit - similar thing, just does not pop up as often. So @dstillman you are right, it must be some backend config of zotero-server that is the real culprit.

@zotero zotero deleted a comment from abaevbog Jun 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants