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

Add a test to check the download of the latest version #648

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

Conversation

r0qs
Copy link
Member

@r0qs r0qs commented Aug 7, 2022

This PR attempt to solve the issue #632. It adds a test to verify if the current version is equal to the downloaded one, and it also modifies the downloader script to enable its use in the tests.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.6%) to 83.099% when pulling 4d5ccb6 on r0qs:test-download-latest-version into c802964 on ethereum:master.

@cameel
Copy link
Member

cameel commented Aug 8, 2022

Thanks for the PR!

I'll take a closer look at it later but for now just wanted to say that solidity-solcjs-ext-test job is failing so there must still be something wrong there.

Also, the coverage bot says the coverage decreased, which means you need to add some more tests.

@r0qs
Copy link
Member Author

r0qs commented Aug 8, 2022

The coverage decrease seems to be because I separated the downloadCurrentVersion.ts into two files, exported getVersionList and downloadBinary to be used on the test, but didn't add tests in case the download fails (e.g., HTTP 404).
I believe these were not covered before either because the original code only logs and exits on error.

But I can add tests for it. However, maybe it would be better to mock the HTTP requests in those methods and pass the endpoint URL as parameter. What do you think?

About the CI, the problem is that I'm getting the latest version based on the version field in the package.json.
But the CI updates the version to one patch version ahead, which was not released yet, so the test fails:

/tmp/ext-test-solc-js-nIDFB9
Using compiler version 0.8.16-ci.2022.8.5+commit.49a2db99.Emscripten.clang
Updating index.js file...
Copying determinism.js...
Copying contracts...
Copying SMTChecker tests...
Updating package.json to version 0.8.16
v0.8.16
Replacing fixed-version pragmas...
Running test function...
...

not ok 1120 Version 0.8.16 is not the latest release 0.8.15

...

Maybe I misunderstood the goal of the task. Should I not use the latest version in the package.json when trying to download? And instead, should I only test if the latest available version in the endpoint is the one that got downloaded?

@cameel
Copy link
Member

cameel commented Aug 10, 2022

But I can add tests for it. However, maybe it would be better to mock the HTTP requests in those methods and pass the endpoint URL as parameter. What do you think?

Yeah, definitely. I actually think that in the JS tests we would be better off with mocks both for positive and negative case. I'd consider an actual download an integration test and for that we might just go all the way - i.e. have a CI job that executes the script and does the check in Bash rather than trying to do it in JS. But, well, I'm not against having that part in JS - it's not like other tests here are pure unit tests :) It's a bit of a mess so whatever works is fine.

BTW, would mocking require adding some dependencies? We overall prefer to avoid too many deps - we have enough already and we should actually trim that even more.

Maybe I misunderstood the goal of the task. Should I not use the latest version in the package.json when trying to download?

Are you sure you're really getting the latest release version? 0.8.16-ci.2022.8.5+commit.49a2db99.Emscripten.clang is not a release version. It's a build from CircleCI. Not sure why you're actually getting this - https://binaries.soliditylang.org/bin/ (https://github.com/ethereum/solc-bin/tree/gh-pages/bin) has nightlies too and you might be getting that but then you'd have nightly in the version string, not ci.

@r0qs
Copy link
Member Author

r0qs commented Aug 13, 2022

Yeah, definitely. I actually think that in the JS tests we would be better off with mocks both for positive and negative case. I'd consider an actual download an integration test and for that we might just go all the way - i.e. have a CI job that executes the script and does the check in Bash rather than trying to do it in JS. But, well, I'm not against having that part in JS - it's not like other tests here are pure unit tests :) It's a bit of a mess so whatever works is fine.

Great. I will do that then. Mocking the JS tests and adding the integration test in the CI.

BTW, would mocking require adding some dependencies? We overall prefer to avoid too many deps - we have enough already and we should actually trim that even more.

No, not necessarily. We can use the native HTTPS module of Node.js. So no new dependencies are needed :-)

Are you sure you're really getting the latest release version? 0.8.16-ci.2022.8.5+commit.49a2db99.Emscripten.clang is not a release version. It's a build from CircleCI. Not sure why you're actually getting this - https://binaries.soliditylang.org/bin/ (https://github.com/ethereum/solc-bin/tree/gh-pages/bin) has nightlies too and you might be getting that but then you'd have nightly in the version string, not ci.

I'm getting the current version from the package.json. See this line. And the released version is fetched from the "releases" entry in the list.json in this line.
The problem was that version 0.8.16 was set in the package.json by the CI but did not exist in the list.json as a release.

function getVersionList () {
console.log('Retrieving available version list...');

return new Promise<string>((resolve, reject) => {
Copy link
Member

Choose a reason for hiding this comment

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

Any reason to directly use promises rather than async/await here?

Copy link
Member Author

@r0qs r0qs Sep 5, 2022

Choose a reason for hiding this comment

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

Yes. As far as I know the https.getmodule from nodejs is not "awaitable" so I needed to wrap it in a promise and explicitly resolve the response.

return new Promise<string>((resolve, reject) => {
const mem = new MemoryStream(null, { readable: false });
https.get('https://binaries.soliditylang.org/bin/list.json', function (response) {
if (response.statusCode !== 200) {
Copy link
Member

Choose a reason for hiding this comment

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

It's something that has already been here before but we should change this so that anything between 200 and 299 is a success. I think we also have the same check in other places in the code

But I'd do it in a separate PR since it's a functional change, not just a refactor and is also unrelated to tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

response.ok?

Copy link
Member Author

@r0qs r0qs Nov 4, 2022

Choose a reason for hiding this comment

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

I don't think the https nodejs module has such ok property. I know that the response object of the fecth API has it, but it is not what we are using here. However, we could mimic its behavior.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, you're right, I was actually looking at the fetch API when I made the comment.

downloadCurrentVersion.ts Outdated Show resolved Hide resolved
test/downloader.ts Outdated Show resolved Hide resolved
@cameel
Copy link
Member

cameel commented Aug 17, 2022

I'm getting the current version from the package.json. See this line. And the released version is fetched from the "releases" entry in the list.json in this line.
The problem was that version 0.8.16 was set in the package.json by the CI but did not exist in the list.json as a release.

Oh, you're right. Looks like the external test for solc-js that we have in the main repo actually bumps version in package.json. It's actually that test that's getting a binary from CI - and it's because it's supposed to test that the latest compiler binary works with solc-js. It's bumping version because solc-js and the compiler have different conventions for updating the version. In the main repo, we bump the version hard-coded in the main CMakeLists.txt immediately after a release while in solc-js we bump version in package.json just before a release. This means that version in solc-js is one number behind solc for most of the development cycle.

In any case, this just shows that this must be tested from the outside. I.e. we should not be assuming inside these JS tests that version in package.json is the most recent one. Instead this should be a Bash integration that installs solc-js on its own (so it can ensure that package.json was not changed), invokes downloadCurrentVersion.ts and makes sure it downloaded the right thing.

@gitguardian
Copy link

gitguardian bot commented Sep 17, 2022

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
Once a secret has been leaked into a git repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Our GitHub checks need improvements? Share your feedbacks!

@r0qs
Copy link
Member Author

r0qs commented Sep 17, 2022

I added the unit tests for downloadBinary and getVersionList. I decided to use a dependency called nock to easily mock the HTTPS requests.
I also added a dummy certificate that is only used in the tests, otherwise we would need to rewrite the downloadBinary and getVersionList to not use the HTTPS module directly but also support HTTP.

I opened another PR #659 for the CI bash integration test.

Copy link
Contributor

@matheusaaguiar matheusaaguiar left a comment

Choose a reason for hiding this comment

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

I am actually learning JS/TS more than anything with this review, but here's my 2 cents :)

downloadCurrentVersion.ts Outdated Show resolved Hide resolved
downloader.ts Outdated Show resolved Hide resolved
test/downloader.ts Outdated Show resolved Hide resolved
test/downloader.ts Outdated Show resolved Hide resolved
downloadCurrentVersion.ts Outdated Show resolved Hide resolved
downloader.ts Outdated Show resolved Hide resolved
test/downloader.ts Outdated Show resolved Hide resolved
test/downloader.ts Outdated Show resolved Hide resolved
r0qs and others added 4 commits November 2, 2022 09:09
Co-authored-by: matheusaaguiar <95899911+matheusaaguiar@users.noreply.github.com>
Co-authored-by: matheusaaguiar <95899911+matheusaaguiar@users.noreply.github.com>
Co-authored-by: matheusaaguiar <95899911+matheusaaguiar@users.noreply.github.com>
Copy link
Contributor

@matheusaaguiar matheusaaguiar left a comment

Choose a reason for hiding this comment

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

LGTM.

@r0qs r0qs self-assigned this Mar 20, 2023
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.

None yet

5 participants