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

services/horizon: Move integration tests away from stellar/quickstart. #3143

Merged
merged 46 commits into from
Nov 5, 2020

Conversation

Shaptic
Copy link
Contributor

@Shaptic Shaptic commented Oct 20, 2020

PR Checklist

PR Structure

  • This PR has reasonably narrow scope (if not, break it down into smaller PRs).
  • This PR avoids mixing refactoring changes with feature changes (split into two PRs
    otherwise).
  • This PR's title starts with name of package that is most changed in the PR, ex.
    services/friendbot, or all or doc if the changes are broad or impact many
    packages.

Thoroughness

  • This PR adds tests for the most critical parts of the new functionality or fixes.
  • I've updated any docs (developer docs, .md
    files, etc... affected by this change). Take a look in the docs folder for a given service,
    like this one.

Release planning

  • I've updated the relevant CHANGELOG (here for Horizon) if
    needed with deprecations, added features, breaking changes, and DB schema changes.
  • I've decided if this PR requires a new major/minor version according to
    semver, or if it's mainly a patch change. The PR is targeted at the next
    release branch if it's not a patch change.

What

This moves the integration test infrastructure away from creating a stellar/quickstart:testing instance for each test, preferring instead to use the modular Docker Compose method.

Why

We want more flexibility with our integration tests; see #3037 for more discussion.

This closes #3031 and closes #3121.

Known limitations

A couple of kinks:

  • Ctrl+C is unreliable as far as cleanup goes, but per discussion below we may want to address this in a later PR, since it it that failing tests are properly handled on the next run.

@Shaptic Shaptic self-assigned this Oct 20, 2020
@cla-bot cla-bot bot added the cla: yes label Oct 20, 2020
@Shaptic Shaptic changed the title services/horizon: Move away from the stellar/quickstart image in integration tests. services/horizon: Move integration tests away from stellar/quickstart. Oct 20, 2020
@Shaptic Shaptic requested a review from a team October 20, 2020 20:15
@Shaptic Shaptic marked this pull request as ready for review October 20, 2020 20:15
go.list Outdated Show resolved Hide resolved
@@ -635,3 +518,9 @@ func panicIf(err error) {
panic(err)
}
}

func fatalIf(t *testing.T, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not in a scope of this PR but can we replace panicIf with fatalIf. I can be wrong but I think I noticed that Cleanup is not called in case of panic.

// directory of the project.
current, err := os.Getwd()
fatalIf(t, err)
for !directoryContains(current, "go.mod") {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think in correctly configured environment you should be able to find the project root by concatenating $GOPATH env variable and src/github.com/stellar/go.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I gather, this would give you the go get version on the master branch, but I think we're much likelier to want to use our local branch/repo. Unless, of course, I don't fall into the category of a "correctly configured environment" 😅

Copy link
Contributor

Choose a reason for hiding this comment

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

This is what I mean by correctly configured environment but I should rather say typical environment. AFAIR, since go modules were introduced there were some issues when the code was outside $GOPATH. We can leave existing code if it works, it was more nit.

services/horizon/internal/test/integration/integration.go Outdated Show resolved Hide resolved
core-upgrade:
restart: on-failure
image: curlimages/curl:7.69.1
command: ["-v", "-f", "http://host.docker.internal:11626/upgrades?mode=set&upgradetime=1970-01-01T00:00:00Z&protocolversion=13"]
command: ["-v", "-f", "http://host.docker.internal:11626/upgrades?mode=set&upgradetime=1970-01-01T00:00:00Z&protocolversion=${PROTOCOL_VERSION:-14}"]
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can upgrade to the latest version available if it's not set?

@2opremio
Copy link
Contributor

2opremio commented Oct 22, 2020

@Shaptic could you please make sure that the captive-core integration tests (which are currently disabled until #3144 is finished ) are also ported?

@@ -419,6 +418,9 @@ jobs:
command: |
echo "export HORIZON_INTEGRATION_TESTS=true" >> $BASH_ENV
echo "export HORIZON_BIN_DIR=~/go/src/github.com/stellar/go" >> $BASH_ENV
- run:
name: Pull latest Stellar Core image
command: docker pull stellar/stellar-core
Copy link
Contributor

Choose a reason for hiding this comment

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

I think I would pin this to a specific version

Copy link
Contributor

Choose a reason for hiding this comment

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

It's worth checking the latest version to confirm it tests work with the latest core version.

@@ -0,0 +1,28 @@
# simple configuration for a standalone test "network"
# see stellar-core_example.cfg for a description of the configuration parameters
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you consider using a template instead of having multiple configuration files?

Copy link
Contributor

Choose a reason for hiding this comment

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

could you elaborate on how we could use a template here (e.g. what templating engine would we use, how would we invoke the template to generate the actual configuration we need) ?

Copy link
Contributor

@2opremio 2opremio Oct 30, 2020

Choose a reason for hiding this comment

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

e.g. https://golang.org/pkg/text/template/ would probably be enough , you would need to use Go (e.g. from the integration tests) to fill it in.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok, I think we'll definitely take this approach if we need to generate several stellar core configurations for the different integration test cases. for now it seems that this stellar core configuration will work for all the integration test cases

context.Background(),
types.ContainerListOptions{All: true, Quiet: true})
// Lets you check if a particular directory contains a file.
directoryContains := func(root string, needle string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
directoryContains := func(root string, needle string) bool {
directoryContainsFileName := func(dir string, filenameToFind string) bool {

}
// Walk up the tree until we find "go.mod", which we treat as the root
// directory of the project.
current, err := os.Getwd()
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't this assume you run the integration tests from the current directory? I am not sure this will always be the case (e.g. from IDEs).

Maybe this will work https://stackoverflow.com/a/18537792/1914440

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only assumption is that the test is run from somewhere within the project. I tried a few methods: your linked one, an approach via runtime.Caller, and the above. This one appeared to be the most reliable; however, I could be wrong (esp. since Goland, Sublime, and VS Code probably all do things slightly differently) and we may need to adjust this.

@2opremio
Copy link
Contributor

  • I've only tested on Linux so far (for obvious reasons) which has some quirks relative to other platforms, purely judging from the start.sh script we have.

  • Ctrl+C reaaaally does not work well, and I haven't looked at what happens when tests fail, either.

  • It's still TBD whether or not we want to run the horizon-postgres container: from a "just let me run the tests" perspective, it might be better/cleaner to keep the DBs as self-contained as possible.

Is this resolved?

assert.NoError(t, err)

// Wait for the third checkpoint ledger and state verification trigger
// Core will push to history archives *after* checkpoint ledger
itest.CloseCoreLedgersUntilSequence(thirdCheckpoint + 1)
err = itest.CloseCoreLedgersUntilSequence(thirdCheckpoint + 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

+1

@tamirms
Copy link
Contributor

tamirms commented Oct 30, 2020

I've only tested on Linux so far (for obvious reasons) which has some quirks relative to other platforms, purely judging from the start.sh script we have.

I've removed the platform specific quirks so it should work on all operating systems which can run docker-compose. I've run the tests locally on my macbook and on linux via circleci.

It's still TBD whether or not we want to run the horizon-postgres container: from a "just let me run the tests" perspective, it might be better/cleaner to keep the DBs as self-contained as possible.

Let's not run the horizon-postgres container for now.

Ctrl+C reaaaally does not work well, and I haven't looked at what happens when tests fail, either.

When the tests fail, the cleanup hook will destroy all the docker containers created by the integration tests.
Ctrl+C seems to abort instantly for me. However, when I Ctrl+C the docker containers from the integration tests are still running.

Stellar Core recently modified its database schema which consequently broke the SQL queries used in dump_core_db.sh.
This commit fixes the SQL queries so that it works with the latest version of Stellar Core.
This commit also adds support for claimable balances which were introduced in Protocol 14/15.
@Shaptic
Copy link
Contributor Author

Shaptic commented Nov 3, 2020

I refactored a small bit regarding how we find the docker-compose file in the latest changes 0c0d0b7.

Unrelated to the above (fails w/ and w/o the changes), but on my local it looks like a single test will fail intermittently with a "still ingesting" error. I've tried but can't track down the cause; it appears to only happen on either TestProtocol14StateVerifier or TestProtocol15Basics. Not when run individually, mind you, but if all of the tests are run.

I can definitely see our introduction of concurrency to testing (incl. the captive core stuff) causing hard-to-track-down and Heisenbug-esque test failures. I'm not sure if this is just something mucked up with my environment, but are we ready to merge this?

@Shaptic Shaptic force-pushed the no-more-quickstart branch from 4ede3af to a5096f4 Compare November 3, 2020 07:55
@tamirms
Copy link
Contributor

tamirms commented Nov 3, 2020

@Shaptic I thought I fixed the "still ingesting" error earlier in 016c91e . But then I saw your comment and was able to reproduce the error in CircleCI. I finally figured out the cause and it's because the root endpoint determines the sequence numbers from a global ledger.State variable. This global variable is mutable and persists between test runs. Horizon periodically calls ledger.SetState() to update the variable. However, it's possible that the check in 016c91e is executed before ledger.SetState() is called for the first time by the new Horizon instance.

In 027a48c , I make sure to clear the ledger state after every test run. This will ensure that waitForHorizon() will make sure to wait until Horizon ingestion is ready.

I have run the integration tests on CircleCI 5 times with this latest fix and so far there haven't been any failures.

@Shaptic
Copy link
Contributor Author

Shaptic commented Nov 3, 2020

Wow, ridiculously subtle, thanks for tracking that down. I ran the suite a couple times locally, as well: only seeing green ✔️ 🎉. I think we can push back resolving the Ctrl+C inconsistencies to another PR to get this in and running, what do you think?

@stellar/horizon-committers anything we're missing? I think we're ready to merge.

services/horizon/docker/docker-compose.standalone.yml Outdated Show resolved Hide resolved
i.app.Close()
// Clear the ledger state otherwise the root response
// will contain ledger information from the previous test run
ledger.SetState(ledger.State{})
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch @tamirms. Created an issue for this: #3195.

services/horizon/internal/test/integration/integration.go Outdated Show resolved Hide resolved
@Shaptic Shaptic merged commit 38aec89 into stellar:master Nov 5, 2020
@Shaptic Shaptic deleted the no-more-quickstart branch November 5, 2020 22:20
tamirms added a commit that referenced this pull request Nov 12, 2020
horizon/ledger.State is a global variable. This is a bad pattern and caused some issues (see #3143). We should make the state local to horizon.App and pass a pointer to it to other parts of the system that need it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants