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

Refactor: Use exvcr to record eth/rootchain network requests #1037

Merged
merged 25 commits into from
Oct 19, 2019

Conversation

achiurizo
Copy link
Contributor

@achiurizo achiurizo commented Oct 7, 2019

📋 #709

TODO

  • Fix skip test for has_token/2 due to ald contract function change
  • Fix skip test for get_deposits due to invalid output encoding
  • Fix CircleCI where passing in --umbrella breaks the exvcr usage.

Overview

This PR introduces exvcr to record the response we get from the Ethereum client for testing with OMG.Eth, OMG.Eth.RootChain and the rest of its ilk. This will record our tests and allows us to turn down the service and test against those responses instead of spinning up, and tearing down the geth process each time for each test case.

It also introduces another way for us to run our tests against an ethereum client by setting up a docker service to bring up the client instead of using DevHelpers to bring up and teardown the geth process.

Recording VCR Cassettes with Docker + ExVCR

Spin up the docker instance for ganache/plasma-contracts:

docker-compose -f docker-compose-fixtures.yml up ganache plasma-contracts

This will spin up ganache in a deterministic mode and deploy the ALD contracts from plasma_framework see here

In your test cases, you can specify the pre-determined addresses (see ganache output in docker) in the setup block. Then just wrap your network calls in use_cassette:

test "get_height/1 returns me a number", %{contract: contract} do
  use_cassette "get_height" do
    OMG.Eth.get_height(contract)
  end
end

Changes

  • introduce exvcr and record geth responses 9e6148f
  • Breaks out tests into separate files for each module, e.g eth_test.exs and root_chain_test.exs 9e6148f
  • reset Ethereuemex into request counter so that we can have a consistent recording. This changes the DevHelpers and test setup block to explicitly reset the counter to 0. 5d9d9f1 8e38bb9
  • adds a docker-compose-fixtures.yml to spin up ganache and plasma-contracts. Note, currently dumped the service here and can consolidate it after. 14d009f

Testing

mix test --only common test/omg_eth/eth_test.exs
mix test --only common test/omg_eth/root_chain_test.exs
# or do it all
mix test --only common

When we use the `@tag fixtures:` functionality, it calls out to
`DevGeth` and etc ... which will send out a request from Ethereumex to
ensure that geth is loaded. This whoever causes the request id to
increment and causes all the cassettes to not much when you remove the
fixtures call. We explicitly reset the counter before we start the
actual interactions in the tests.
Need to reset the :rpc_counter on Ethereuemex so that we can have the
exvcr cassettes record it in a predicatble manner(start with id 1)
skipped a few tests due to some issues see comments for more details:

* `hasToken` not the ALD contract function anymore
* `get_deposits/3` running into output encoding errors
@achiurizo
Copy link
Contributor Author

I think the --umbrella flag in the common_coveralls_and_integration_tests is breaking the exvcr usage. 🤔

Copy link
Contributor

@pdobacz pdobacz left a comment

Choose a reason for hiding this comment

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

just some comments first to ramp up, as this is a Draft for now, but looks good 👍

My biggest concern for now is:

  • how do I actually record the cassettes from scratch? There is a section in the PR description, but I'm not sure if this is complete. I'd assume one would need to bypass exvcr replaying of cassettes and instead have it record them? How are the json files updated in practice
  • related but a bit separate: how do I just run those tests with exvcr entirely bypassed, using geth, parity (or ganache, since it's supported now)?

# The problem is the fixtures would send a first request out(this request). When you remove the fixtures,
# Ethereumex thinks we are sending the first request, missing the matching cassettes by request_body.
# So, we reset the counter so the cassettes can reply correctly without the fixtures:
:ets.insert(:rpc_requests_counter, {:rpc_counter, 0})
Copy link
Contributor

Choose a reason for hiding this comment

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

how about splitting this one-liner into its function (can be put under test/support) so that the docs can be put there too. Then it will make the docs find-able for anyone looking at any of the 6 occurrences of this insert

Copy link
Contributor

Choose a reason for hiding this comment

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

what do you think about this?

@pdobacz
Copy link
Contributor

pdobacz commented Oct 8, 2019

also on this:

Fix CircleCI where passing in --umbrella breaks the exvcr usage.

I don't have any hints yet, why this would hurt coveralls. Are you able to run CircleCI's invocation locally (or in whichever setup where you have the mix test invocations pass)? That would be more or less these (note the different paths):

mix coveralls --umbrella --only common apps/omg_eth/test/omg_eth/eth_test.exs
mix coveralls --umbrella --only common apps/omg_eth/test/omg_eth/root_chain_test.exs
# or do it all
mix coveralls --umbrella --only common

Also to troubleshoot a bit more, can you run

mix coveralls --umbrella --only common apps/omg_eth/test/omg_eth/eth_test.exs

for elixir-omg/master and see what happens?

Ping me if you get stuck, I'll try to reproduce the problem on my end.

@pdobacz
Copy link
Contributor

pdobacz commented Oct 8, 2019

Ha, actually I played around with this and got something.

If you run the coveralls invocations, you'll see that exvcr attempts generate new cassettes under a parent dir (outside apps/omg_eth). This is because our coveralls --umbrella runs in the root dir, not in the app subdir :(.

Hence the econnrefused are coming from attempts to talk to ganache and record the cassettes. Not sure how to make exvcr choose the correct root path.

@InoMurko
Copy link
Contributor

THIS IS MAJOR 👏 👏 👏 <3 <3 <3

@coveralls
Copy link

coveralls commented Oct 11, 2019

Coverage Status

Coverage remained the same at 84.671% when pulling 2b10b91 on achiurizo/exvcr into e7cae6a on master.

@achiurizo
Copy link
Contributor Author

@pdobacz

how do I actually record the cassettes from scratch? There is a section in the PR description, but I'm not sure if this is complete. I'd assume one would need to bypass exvcr replaying of cassettes and instead have it record them? How are the json files updated in practice

Wrapping the code executing the network request will update the json. Depending on your matching preference, it will automatically re-record if it does not have an existing record.

related but a bit separate: how do I just run those tests with exvcr entirely bypassed, using geth, parity (or ganache, since it's supported now)?

Haven't tried this but seems like the approach is to pass in another option like:

use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney, options: [clear_mock: true]

@achiurizo achiurizo marked this pull request as ready for review October 15, 2019 11:12
@achiurizo achiurizo requested review from InoMurko and pdobacz October 15, 2019 11:13
@@ -0,0 +1,22 @@
version: "3.4"
Copy link
Contributor

Choose a reason for hiding this comment

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

can we get some docs around this so that we know how to record for new "tests"?

Copy link
Contributor

@pdobacz pdobacz left a comment

Choose a reason for hiding this comment

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

3 minor follow-ups to the previous comments

# The problem is the fixtures would send a first request out(this request). When you remove the fixtures,
# Ethereumex thinks we are sending the first request, missing the matching cassettes by request_body.
# So, we reset the counter so the cassettes can reply correctly without the fixtures:
:ets.insert(:rpc_requests_counter, {:rpc_counter, 0})
Copy link
Contributor

Choose a reason for hiding this comment

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

what do you think about this?

@achiurizo achiurizo merged commit 105a52d into master Oct 19, 2019
@achiurizo achiurizo deleted the achiurizo/exvcr branch October 19, 2019 04:39
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.

4 participants