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

ping/rust: introduce rust cross-version test #26

Merged
merged 35 commits into from
Aug 22, 2022

Conversation

laurentsenta
Copy link
Collaborator

@laurentsenta laurentsenta commented Jul 6, 2022

  • Update the ping test with a rust version.
  • Provide composition files to run
    • rust - rust interoperability tests
    • rust - go interoperability tests (latest versions)
    • rust - go interoperability tests (mix of versions)

Rust ping test:

We add a ping/rust source folder. This test follows the workflow implemented by ping/go which means they may be combined.

  • It defines a features flag to switch between versions in the Cargo.toml
  • It adds a few operations to replace a package, in the Dockerfile.

Testground compositions

Test outputs are shown on the testground dashboard (localhost:8042 for a default daemon that runs locally).

ping/_compositions/rust-cross-versions.toml

Goal: test different rust-libp2p versions together.

This composition tests v0.44.0, v0.45.1, v0.46.0, master, and an optional branch:

Usage:

# required once, run from the libp2p/test-plans folder:
testground import --from ./ --name libp2p

# simple test (all versions + master)
testground run composition -f ping/_compositions/rust-cross-versions.toml --wait

# with a branch:
# GitTarget defaults to github.com/libp2p/rust-libp2p, but you may use a fork.

# this version prints "Hello"
GitTarget=github.com/laurentsenta/rust-libp2p GitReference=demo/pass \
 testground run composition -f ping/_compositions/rust-cross-versions.toml --wait

# this version breaks the ping protocol
GitTarget=github.com/laurentsenta/rust-libp2p GitReference=demo/break \
 testground run composition -f ping/_compositions/rust-cross-versions.toml --wait
  • Note: we do a package rewrite when we build the custom branch,

ping/_compositions/go-rust-interop-latest.toml

Goal: test latest go and rust libp2p versions together.

This composition tests rust master, and go master and a custom branch either go or rust.

Usage:

# required once, run from the libp2p/test-plans folder:
testground import --from ./ --name libp2p

testground run composition -f ping/_compositions/go-rust-interop-latest.toml --wait

# with a rust branch:

# this version prints "Hello"
GitTarget=github.com/laurentsenta/rust-libp2p GitReference=demo/pass InteropTarget=rust \
 testground run composition -f ping/_compositions/go-rust-interop-latest.toml --wait

# this version breaks the ping protocol
GitTarget=github.com/laurentsenta/rust-libp2p GitReference=demo/break InteropTarget=rust \
 testground run composition -f ping/_compositions/go-rust-interop-latest.toml --wait

# with a go branch:

# this version prints "Hello"
GitTarget=github.com/laurentsenta/go-libp2p GitReference=demo/pass InteropTarget=go \
 testground run composition -f ping/_compositions/go-rust-interop-latest.toml --wait

# this version breaks the ping protocol
GitTarget=github.com/laurentsenta/go-libp2p GitReference=demo/break InteropTarget=go \
 testground run composition -f ping/_compositions/go-rust-interop-latest.toml --wait

ping/_compositions/go-rust-interop.toml

Goal: every known go and rust versions together.

This composition combines the version from both rust and go,

Usage:

# required once, run from the libp2p/test-plans folder:
testground import --from ./ --name libp2p

testground run composition -f ping/_compositions/go-rust-interop.toml --wait

# see `go-rust-interop-latest` for the parameters

CI

jobs:
  run-libp2p-test-plans:
    uses: "libp2p/test-plans/.github/workflows/test-compatibility.yml@master"
    with:
      composition_file: "ping-interop/_compositions/rust-cross-versions.toml"
      test_case: "ping"
      custom_git_reference: "current-pr" # optional
      custom_git_target: "my-fork/go-libp2p" # optional
      custom_interop_target: "go" # optional
      testground_endpoint: "https://ci.testground.ipfs.team/" # optional

This action will build & run the test.

Todo:

  • document rust-rust
  • document rust-go latest
  • add rust - go with all runs
    • identify related PRs (stability fix, and others)
  • propose a few ideas to make these tests more palatable when it comes to maintenance
  • remove the debug commit

@laurentsenta laurentsenta marked this pull request as draft July 6, 2022 09:36
# CARGO_PATCH = """
# [patch.crates-io]
# libp2pv0450 = { package = "libp2p", git = "{{ or .Env.GitTarget "https://github.com/libp2p/rust-libp2p" }}", branch = "master" }
# """
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@mxinden fyi, that's how we could get master & current groups as far as I understand, but I get this for now:

Caused by:
   The patch location `https://github.com/libp2p/rust-libp2p` does not appear to contain any packages matching the name `libp2p`.

Copy link
Member

Choose a reason for hiding this comment

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

That is surprising to me. The below works fine in a project of mine:

+
+[patch.crates-io]
+libp2p = { package = "libp2p", git = "https://github.com/libp2p/rust-libp2p", branch = "master" }

Maybe related to the libp2pv0450 rename?

Copy link
Member

Choose a reason for hiding this comment

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

Is this missing the .git suffix, i.e.git = "https://github.com/libp2p/rust-libp2p.git?

@laurentsenta laurentsenta force-pushed the feat/ping-interop-rust branch 2 times, most recently from 812d202 to 9375005 Compare July 7, 2022 17:17
@mxinden
Copy link
Member

mxinden commented Jul 13, 2022

@laurentsenta just as a heads up, I am looking into cleaning up main.rs now. Next would be to implement the second round of pings that the Go implementation does.

@mxinden
Copy link
Member

mxinden commented Jul 14, 2022

Pushed my latest work, mostly refactoring main.rs. I hope you don't mind @laurentsenta.

Running testground run composition -f rust-cross-versions.toml --wait succeeds with 4 instances on my machine 🎉

@mxinden
Copy link
Member

mxinden commented Jul 18, 2022

Update: I started working on running multiple iterations with different latencies, the correspondent Rust code to the Go code below. It works with 4 Rust instances. Still needs some clean-up.

test-plans/ping/go/main.go

Lines 251 to 286 in eee18f0

for i := 1; i <= iterations; i++ {
runenv.RecordMessage("⚡️ ITERATION ROUND %d", i)
// 🤹 Let's calculate our new latency.
latency := time.Duration(rand.Int31n(int32(maxLatencyMs))) * time.Millisecond
runenv.RecordMessage("(round %d) my latency: %s", i, latency)
// 🐌 Let's ask the NetClient to reconfigure our network.
//
// The sidecar will apply the network latency from the outside, and will
// signal on the CallbackState in the sync service. Since we want to wait
// for ALL instances to configure their networks for this round before
// we proceed, we set the CallbackTarget to the total number of instances
// partitipating in this test run. MustConfigureNetwork will block until
// that many signals have been received. We use a unique state ID for
// each round.
//
// Read more about the sidecar: https://docs.testground.ai/concepts-and-architecture/sidecar
initCtx.NetClient.MustConfigureNetwork(ctx, &network.Config{
Network: "default",
Enable: true,
Default: network.LinkShape{Latency: latency},
CallbackState: sync.State(fmt.Sprintf("network-configured-%d", i)),
CallbackTarget: runenv.TestInstanceCount,
})
if err := pingPeers(fmt.Sprintf("iteration-%d", i)); err != nil {
return err
}
// Signal that we're done with this round and wait for others to be
// done before we repeat and switch our latencies, or exit the loop and
// close the host.
doneState := sync.State(fmt.Sprintf("done-%d", i))
initCtx.SyncClient.MustSignalAndWait(ctx, doneState, runenv.TestInstanceCount)
}

@laurentsenta could you prepare a composition file with both a Rust and a Golang node? That would help testing interoperability of the main.rs a lot.

@mxinden
Copy link
Member

mxinden commented Jul 20, 2022

I pushed the code needed to run multiple iterations of the ping test. It should now be interoperable with the Golang implementation, though thus far I have only tested it across different Rust versions.

Comment on lines 16 to 17
# Note: if this version doesn't match EXACTLY the testground one, I got errors.
# Is it possible we get similar issues with libp2p dependencies?
Copy link
Member

Choose a reason for hiding this comment

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

Yes, that is expected behavior. In case we ever hit the same issue with libp2p we can differentiate by version via the passed in libp2p feature flag.

@laurentsenta
Copy link
Collaborator Author

@mxinden I added the testground-related content,
to run a single interop test, use:

# from the test-plans folder, import the plans (once)
testground plan import --from ./ --name libp2p

# then run the simple composition
testground run composition -f ping/_compositions/go-rust-interop-latest.toml --wait 

I have a more complex test ready, BUT the simple one is not passing yet,

This is the error I get:

Jul 21 15:35:51.224502  INFO    2.5231s    MESSAGE << go-v0.20[000] (a78c77) >> my listen addrs: [/ip4/16.3.0.3/tcp/37119]
Jul 21 15:35:51.260018  INFO    2.5588s      ERROR << rust-v0.47.0[000] (a36242) >> thread 'tokio-runtime-worker' panicked at 'JSON Deserialization: Error("invalid type: map, expected a string", line: 1, column: 0)', /usr/local/cargo/git/checkouts/sdk-rust-13727f1421bc2391/d6af289/src/responses.rs:63:54
Jul 21 15:35:51.260053  INFO    2.5588s      ERROR << rust-v0.47.0[000] (a36242) >> stack backtrace:
Jul 21 15:35:51.269283  INFO    2.5680s      ERROR << rust-v0.47.0[000] (a36242) >>    0: rust_begin_unwind
Jul 21 15:35:51.269325  INFO    2.5681s      ERROR << rust-v0.47.0[000] (a36242) >>              at ./rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:584:5
Jul 21 15:35:51.269353  INFO    2.5681s      ERROR << rust-v0.47.0[000] (a36242) >>    1: core::panicking::panic_fmt
Jul 21 15:35:51.269393  INFO    2.5682s      ERROR << rust-v0.47.0[000] (a36242) >>              at ./rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/core/src/panicking.rs:142:14
Jul 21 15:35:51.269425  INFO    2.5682s      ERROR << rust-v0.47.0[000] (a36242) >>    2: core::result::unwrap_failed
Jul 21 15:35:51.269444  INFO    2.5682s      ERROR << rust-v0.47.0[000] (a36242) >>              at ./rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/core/src/result.rs:1785:5
Jul 21 15:35:51.269461  INFO    2.5682s      ERROR << rust-v0.47.0[000] (a36242) >>    3: <testground::responses::Response as core::convert::From<testground::responses::RawResponse>>::from
Jul 21 15:35:51.269484  INFO    2.5683s      ERROR << rust-v0.47.0[000] (a36242) >>    4: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
Jul 21 15:35:51.269502  INFO    2.5683s      ERROR << rust-v0.47.0[000] (a36242) >>    5: tokio::runtime::task::harness::poll_future
Jul 21 15:35:51.269526  INFO    2.5683s      ERROR << rust-v0.47.0[000] (a36242) >>    6: tokio::runtime::task::harness::Harness<T,S>::poll
Jul 21 15:35:51.269544  INFO    2.5683s      ERROR << rust-v0.47.0[000] (a36242) >>    7: std::thread::local::LocalKey<T>::with
Jul 21 15:35:51.269562  INFO    2.5683s      ERROR << rust-v0.47.0[000] (a36242) >>    8: tokio::runtime::thread_pool::worker::Context::run_task
Jul 21 15:35:51.269578  INFO    2.5683s      ERROR << rust-v0.47.0[000] (a36242) >>    9: tokio::runtime::thread_pool::worker::Context::run
Jul 21 15:35:51.269595  INFO    2.5684s      ERROR << rust-v0.47.0[000] (a36242) >>   10: tokio::macros::scoped_tls::ScopedKey<T>::set
Jul 21 15:35:51.269625  INFO    2.5684s      ERROR << rust-v0.47.0[000] (a36242) >>   11: tokio::runtime::thread_pool::worker::run
Jul 21 15:35:51.269693  INFO    2.5684s      ERROR << rust-v0.47.0[000] (a36242) >>   12: <tokio::runtime::blocking::task::BlockingTask<T> as core::future::future::Future>::poll
Jul 21 15:35:51.269721  INFO    2.5685s      ERROR << rust-v0.47.0[000] (a36242) >>   13: tokio::runtime::task::harness::Harness<T,S>::poll
Jul 21 15:35:51.269742  INFO    2.5685s      ERROR << rust-v0.47.0[000] (a36242) >>   14: tokio::runtime::blocking::pool::Inner::run
Jul 21 15:35:51.269762  INFO    2.5685s      ERROR << rust-v0.47.0[000] (a36242) >> note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

I'm looking into it, one thing to note, it looks like the rust test publishes a raw string address (local_addr.to_string()), while the go test publishes a struct

@laurentsenta laurentsenta mentioned this pull request Jul 28, 2022
6 tasks
Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

@laurentsenta thanks for merging the JSON changes and the iteration fix.

Should I test this locally or did you already get to it?

.parse()
.unwrap();

for i in 1..iterations + 1 {
Copy link
Member

Choose a reason for hiding this comment

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

Good catch @laurentsenta.

@laurentsenta laurentsenta changed the title (wip) ping/rust: introduce rust cross-version test ping/rust: introduce rust cross-version test Aug 18, 2022
@laurentsenta laurentsenta force-pushed the feat/ping-interop-rust branch 2 times, most recently from a6137e7 to 8e33cce Compare August 19, 2022 09:13
@laurentsenta laurentsenta marked this pull request as ready for review August 19, 2022 09:14
@laurentsenta
Copy link
Collaborator Author

Marking this as ready for review, we had a call with @mxinden and decided we can merge, try rust - go interop on rust-libp2p, and improve performance.

Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

Cool. Let's go ahead here and iterate on it afterwards.

- Do once, from the test-plans root: import the test-plans with `testground plan import ./ --name libp2p`
- Run the test with `testground run composition -f ping/_compositions/go-cross-versions.toml --wait`

## How to add a new version to ping/rust
Copy link
Member

Choose a reason for hiding this comment

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

🚀

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.

3 participants