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

* ping/go: fix composition name

* ping/rust: introduce the ping/rust test

* Showcase version selection through features

Can be run with `cargo check --features libp2pv0450` or `cargo check --features
libp2pv0440`.

* Peer programming session

* ping/rust: experiment with master & current groups

* ping/rust/src/main: Simplify import across versions

* ping/rust/src/main: Remove commented out code

* ping/rust/src/main: Clean up

* ping/rust/Dockerfile: Update crates.io index in separate step

Potentially allows caching.

* ping/rust/Dockerfile: Don't both build and install

Building the binary in release mode is enough.

* ping/rust/src/main: Clean up log lines

* ping/rust: Implement iterations with latency

* ping/rust/src/main: Extract signal and wait logic into fn

* ping/rust/Dockerfile: import caching fixes

* ping/: add cross-version composition

* ping/rust: add json payloads fix

* ping/rust: match iterations id with go

* ping/rust/Dockerfile: improve caching

* ci: introduce workflow ping-interop-rust

* ping/interop: update latest versions

* ping/_compositions: add full ping interop

* ci: resolve git reference to sha

* ping/rust/Dockerfile: drop cargo output

* ping/rust: drop version indirection

* ping/rust/Dockerfile: fix features to support caching

* ping/rust/Dockerfile: do not cache the rewritten package

* ping/_compositions/*: use concurrent_builds

* ping/_compositions/*: drop test_instances count

* ci: build composition then run

* ping: introduce InteropTarget option

* ci: fix interop target & build

* ping/_compositions/*: introduce load_resource

* ci: 10 minutes timeout for the run step

* README: add update instruction for rust & clean go

* ping/rust/Dockerfile: add protocol buffer compiler

* ping/rust/Cargo.lock: cargo update packages

* .github: increase testground timeout

Co-authored-by: Max Inden <mail@max-inden.de>
This commit is contained in:
Laurent Senta 2022-08-22 12:25:07 +02:00 committed by GitHub
parent 3f6b90969d
commit 072d351a5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 4959 additions and 107 deletions

View File

@ -35,7 +35,7 @@ runs:
cat <<EOF >> ~/testground/.env.toml
[daemon.scheduler]
task_timeout_min = 30
task_timeout_min = 60
EOF
testground daemon > testground.out 2> testground.err &
fi;

View File

@ -26,5 +26,5 @@ jobs:
with:
composition_file: "ping/_compositions/go-cross-versions.toml"
custom_git_target: ${{ github.event.inputs.custom_git_target }} # nothing or "some-fork/go-libp2p"
custom_git_reference: ${{ github.event.inputs.custom_git_reference }} # a git reference
custom_git_reference: ${{ github.event.inputs.custom_git_reference }} # a git branch
testground_endpoint: ${{ github.event.inputs.testground_endpoint }}

30
.github/workflows/ping-interop-rust.yml vendored Normal file
View File

@ -0,0 +1,30 @@
on:
workflow_dispatch:
inputs:
testground_endpoint:
type: string
required: false
description: testground endpoint
custom_git_reference:
type: string
required: false
description: rust ref
custom_git_target:
type: string
required: false
description: repository to use as replace target
default: github.com/libp2p/rust-libp2p
name: rust-libp2p ping - rust test with testground.
jobs:
run-libp2p-test-plans:
# If you intend to use this workflow from another repo,
# you need to pass the repo and the version:
# uses: "libp2p/test-plans/.github/workflows/run-composition.yml@master"
uses: "./.github/workflows/run-composition.yml"
with:
composition_file: "ping/_compositions/rust-cross-versions.toml"
custom_git_target: ${{ github.event.inputs.custom_git_target }} # nothing or "some-fork/go-libp2p"
custom_git_reference: ${{ github.event.inputs.custom_git_reference }} # a git reference
testground_endpoint: ${{ github.event.inputs.testground_endpoint }}

39
.github/workflows/ping-interop.yml vendored Normal file
View File

@ -0,0 +1,39 @@
on:
workflow_dispatch:
inputs:
testground_endpoint:
type: string
required: false
description: testground endpoint
custom_git_reference:
description: the git commit or branch we're going to use for the custom target
required: false
type: string
custom_git_target:
description: the custom git fork url we're going to use for the custom target (github.com/some-fork/rust-libp2p)
required: false
type: string
custom_interop_target:
description: in the case of cross-implementation testing, the implementation target (go | rust | ...)
required: false
type: string
name: libp2p ping - go and rust test with testground.
jobs:
run-ping-latest:
uses: "./.github/workflows/run-composition.yml"
with:
composition_file: "ping/_compositions/go-rust-interop-latest.toml"
custom_git_target: ${{ github.event.inputs.custom_git_target }} # nothing or "some-fork/go-libp2p"
custom_git_reference: ${{ github.event.inputs.custom_git_reference }} # a git reference
custom_interop_target: ${{ github.event.inputs.custom_interop_target }} # go | rust
testground_endpoint: ${{ github.event.inputs.testground_endpoint }}
run-ping-all:
uses: "./.github/workflows/run-composition.yml"
with:
composition_file: "ping/_compositions/go-rust-interop.toml"
custom_git_target: ${{ github.event.inputs.custom_git_target }} # nothing or "some-fork/go-libp2p"
custom_git_reference: ${{ github.event.inputs.custom_git_reference }} # a git reference
custom_interop_target: ${{ github.event.inputs.custom_interop_target }} # go | rust
testground_endpoint: ${{ github.event.inputs.testground_endpoint }}

View File

@ -4,12 +4,19 @@ on:
workflow_call:
inputs:
composition_file:
description: the workflow we're going to run
required: true
type: string
custom_git_reference:
description: the git commit or branch we're going to use for the custom target
required: false
type: string
custom_git_target:
description: the custom git fork url we're going to use for the custom target (github.com/some-fork/rust-libp2p)
required: false
type: string
custom_interop_target:
description: in the case of cross-implementation testing, the implementation target (go | rust | ...)
required: false
type: string
testground_endpoint:
@ -39,12 +46,29 @@ jobs:
working-directory: ./test-plans
run: |
testground plan import --from ./ --name libp2p
- name: Run the composition file
- name: Resolve the git references
if: ${{ inputs.custom_git_reference && inputs.custom_git_target }}
id: resolve_reference
working-directory: ./test-plans
run: |
GitReference=${{ inputs.custom_git_reference }} \
GitTarget=${{ inputs.custom_git_target }} \
testground run composition \
git fetch https://${{ inputs.custom_git_target }} ${{ inputs.custom_git_reference }}
SHA=`git log FETCH_HEAD -n 1 --pretty=format:"%H"`
echo "::set-output name=custom_git_sha::${SHA}"
- name: Build the composition file
working-directory: ./test-plans
run: |
testground build composition \
-f ${{ inputs.composition_file }} \
--wait
env:
GitReference: ${{ steps.resolve_reference.outputs.custom_git_sha || inputs.custom_git_reference }}
GitTarget: ${{ inputs.custom_git_target }}
InteropTarget: ${{ inputs.custom_interop_target }}
- name: Run the composition file
working-directory: ./test-plans
timeout-minutes: 10
run: |
testground run composition \
-f ${{ inputs.composition_file }} \
--metadata-repo "${GITHUB_REPOSITORY}" \
--metadata-branch "${GITHUB_REF#refs/heads/}" \
@ -52,7 +76,9 @@ jobs:
--collect-file ./result.tgz \
--collect --wait
env:
GitReference: ${{ inputs.custom_git_reference }}
GitReference: ${{ steps.resolve_reference.outputs.custom_git_sha || inputs.custom_git_reference }}
GitTarget: ${{ inputs.custom_git_target }}
InteropTarget: ${{ inputs.custom_interop_target }}
- uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:

View File

@ -9,10 +9,9 @@ This repository contains Testground test plans for libp2p components.
When a new version of libp2p is released, we want to make it permanent in the `ping/go` test folder.
1. In the `ping/_compositions/go-cross-versions.toml` file,
- Find the group for the latest version (`v0.20` for example) and copy it into a new group (`v0.21` for example).
- Update the `selectors` (go tags) and `modfile` options. Update the `build_base_image` if needed.
- Increment the `total_instances` flag (near line 7).
1. In the `ping/_compositions/go.toml` file,
- copy the `[master]` section and turn it into a `[[groups]]` item
- update the `[master]` section with the future version
2. In the `ping/go` folder,
- Add a new compatibility shim in `compat/` if needed, or add your new selector to the latest shim (see `compat/libp2p.v0.17.go` for example).
- Create the new mod and sum files (`go.v0.21.mod` for example). Assuming you're updating from `v$A` to `v$B`, a simple way to do this is to:
@ -21,8 +20,23 @@ When a new version of libp2p is released, we want to make it permanent in the `p
- update the `go-libp2p` version, go version, and update the code if needed.
- then `go get -tags v$B && go mod tidy`
3. Run the test on your machine
- Import the test-plans with `testground plan import ./ --name libp2p` (once, from the test-plans root)
- Run with `testground run composition -f ping/_compositions/go-cross-versions.toml --wait`
- 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
When a new version of libp2p is released, we want to make it permanent in the `ping/rust` test folder.
1. In the `ping/_compositions/rust.toml` file,
- Copy the `[master]` section and turn it into a item in the `[[groups]]` array
- Update the `[master]` section with the new master version
2. In the `ping/rust` folder,
- `Cargo.toml`: update the feature flags `libp2pvxxx` to fix the released version and add the new `master`
- `src/main.rs`: Update the `mod libp2p` definition with the new master
- Run `cargo update` if needed. Try to build with `cargo build --features libp2pvxxx`
3. Run the test on your machine
- 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/rust-cross-versions.toml --wait`
## License

View File

@ -1,10 +1,9 @@
[metadata]
name = "go-cross-versions {{ .Env.Reference }}"
name = "go-cross-versions {{ .Env.GitReference }}"
[global]
plan = "libp2p/ping/go"
case = "ping"
total_instances = {{ if .Env.GitReference }}7{{ else }}6{{ end }}
builder = "docker:go"
runner = "local:docker"
@ -14,108 +13,72 @@
go_proxy_mode = "remote"
go_proxy_url = "https://proxy.golang.org"
[[groups]]
id = "v0.11"
instances = { count = 1 }
{{ with (load_resource "./go.toml" ) }}
{{ range .groups }}
[[groups]]
id = "{{ .Id }}"
instances = { count = 1 }
[groups.build]
selectors = ['v0.11']
[groups.build]
selectors = ['{{ .Selector }}']
[groups.build_config]
build_base_image = 'golang:1.14-buster'
modfile = "go.v0.11.mod"
[groups.build_config]
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
{{ end }}
[[groups]]
id = "v0.17"
instances = { count = 1 }
{{ with .master }}
[[groups]]
id = "master"
instances = { count = 1 }
[groups.build]
selectors = ['v0.17']
[groups.build]
selectors = ['{{ .Selector }}']
[groups.build_config]
build_base_image = 'golang:1.16-buster'
modfile = "go.v0.17.mod"
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "master"
[[groups]]
id = "v0.19"
instances = { count = 1 }
[groups.build_config]
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
[groups.build]
selectors = ['v0.19']
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat={{ .GoVersion }}
"""
{{ end }}
[groups.build_config]
build_base_image = 'golang:1.17-buster'
modfile = "go.v0.19.mod"
{{ if $.Env.GitReference }}
{{ with .custom }}
[[groups]]
id = "custom"
instances = { count = 1 }
[[groups]]
id = "v0.20"
instances = { count = 1 }
[groups.build]
selectors = ['{{ .Selector }}']
[groups.build]
selectors = ['v0.20']
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "{{ $.Env.GitReference }}"
{{ if $.Env.GitTarget }}
target = "{{ $.Env.GitTarget }}"
{{ end }}
[groups.build_config]
build_base_image = 'golang:1.18-buster'
modfile = "go.v0.20.mod"
[groups.build_config]
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
[[groups]]
id = "v0.21"
instances = { count = 1 }
[groups.build]
selectors = ['v0.21']
[groups.build_config]
build_base_image = 'golang:1.18-buster'
modfile = "go.v0.21.mod"
[[groups]]
id = "master"
instances = { count = 1 }
[groups.build]
selectors = ['v0.21']
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "master"
[groups.build_config]
build_base_image = 'golang:1.18-buster'
modfile = "go.v0.21.mod"
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat=1.18
"""
{{ if .Env.GitReference }}
[[groups]]
id = "custom"
instances = { count = 1 }
[groups.build]
selectors = ['v0.20']
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "{{ .Env.GitReference }}"
{{ if .Env.GitTarget }}
target = "{{ .Env.GitTarget }}"
{{ end }}
[groups.build_config]
build_base_image = 'golang:1.18-buster'
modfile = "go.v0.20.mod"
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat=1.18
"""
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat={{ .GoVersion }}
"""
{{ end }}
{{ end }}
{{ end }}

View File

@ -0,0 +1,113 @@
[metadata]
name = "go-rust-cross-version"
[global]
plan = "libp2p/ping"
case = "ping"
runner = "local:docker"
concurrent_builds = 1
[global.build_config]
enable_go_build_cache = false # see https://github.com/testground/testground/issues/1361
# disable testground's goproxy which hangs on github runners.
go_proxy_mode = "remote"
go_proxy_url = "https://proxy.golang.org"
{{ with (load_resource "./go.toml") }}
{{ with .master }}
[[groups]]
id = "go-master"
instances = { count = 1 }
builder = "docker:go"
[groups.build]
selectors = ['{{ .Selector }}']
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "master"
[groups.build_config]
path = "./go/"
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat={{ .GoVersion }}
"""
{{ end }}
{{ if eq $.Env.InteropTarget "go" }}
{{ if $.Env.GitReference }}
{{ with .custom }}
[[groups]]
id = "custom-go"
instances = { count = 1 }
builder = "docker:go"
[groups.build]
selectors = ['{{ .Selector }}']
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "{{ $.Env.GitReference }}"
{{ if $.Env.GitTarget }}
target = "{{ $.Env.GitTarget }}"
{{ end }}
[groups.build_config]
path = "./go/"
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat={{ .GoVersion }}
"""
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ with (load_resource "./rust.toml") }}
{{ with .master }}
[[groups]]
id = "rust-master"
instances = { count = 1 }
builder = "docker:generic"
[groups.build_config]
path = "./rust/"
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
{{ end }}
{{ if eq $.Env.InteropTarget "rust" }}
{{ if $.Env.GitReference }}
{{ with .custom }}
[[groups]]
id = "custom-rust"
instances = { count = 1 }
builder = "docker:generic"
[groups.build_config]
path = "./rust/"
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
CARGO_REMOVE = '{{ .CargoFeatures }}'
CARGO_PATCH = """
{{ .CargoFeatures }} = {package = "libp2p", git = "https://{{ or $.Env.GitTarget "github.com/libp2p/rust-libp2p" }}", rev = "{{ $.Env.GitReference }}", default_features = false, features = [ "websocket", "mplex", "yamux", "tcp-async-io", "ping", "noise", "dns-async-std" ], version = "0.47.0", optional = true}
"""
{{ end }}
{{ end }}
{{ end }}
{{ end }}

View File

@ -0,0 +1,141 @@
[metadata]
name = "go-rust-cross-version"
[global]
plan = "libp2p/ping"
case = "ping"
runner = "local:docker"
concurrent_builds = 1
[global.build_config]
enable_go_build_cache = false # see https://github.com/testground/testground/issues/1361
# disable testground's goproxy which hangs on github runners.
go_proxy_mode = "remote"
go_proxy_url = "https://proxy.golang.org"
{{ with (load_resource "./go.toml") }}
{{ range .groups }}
[[groups]]
id = "{{ .Id }}"
instances = { count = 1 }
builder = "docker:go"
[groups.build]
selectors = ['{{ .Selector }}']
[groups.build_config]
path = "./go/"
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
{{ end }}
{{ with .master }}
[[groups]]
id = "master"
instances = { count = 1 }
builder = "docker:go"
[groups.build]
selectors = ['{{ .Selector }}']
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "master"
[groups.build_config]
path = "./go/"
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat={{ .GoVersion }}
"""
{{ end }}
{{ if eq $.Env.InteropTarget "go" }}
{{ if $.Env.GitReference }}
{{ with .custom }}
[[groups]]
id = "custom-go"
instances = { count = 1 }
builder = "docker:go"
[groups.build]
selectors = ['{{ .Selector }}']
[[groups.build.dependencies]]
module = "github.com/libp2p/go-libp2p"
version = "{{ $.Env.GitReference }}"
{{ if $.Env.GitTarget }}
target = "{{ $.Env.GitTarget }}"
{{ end }}
[groups.build_config]
path = "./go/"
build_base_image = 'golang:{{ .GoVersion }}-buster'
modfile = "{{ .Modfile }}"
[groups.build_config.dockerfile_extensions]
# deal with dependency changes in master until we create the new vx.y.z instance
pre_build = """
RUN cd ${PLAN_DIR} && \
go mod download github.com/libp2p/go-libp2p && \
go mod tidy -compat={{ .GoVersion }}
"""
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ with (load_resource "./rust.toml") }}
{{ range .groups }}
[[groups]]
id = "rust-{{ .Id }}"
instances = { count = 1 }
builder = "docker:generic"
[groups.build_config]
path = "./rust/"
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
{{ end }}
{{ with .master }}
[[groups]]
id = "rust-master"
instances = { count = 1 }
builder = "docker:generic"
[groups.build_config]
path = "./rust/"
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
{{ end }}
{{ if eq $.Env.InteropTarget "rust" }}
{{ if $.Env.GitReference }}
{{ with .custom }}
[[groups]]
id = "custom-rust"
instances = { count = 1 }
builder = "docker:generic"
[groups.build_config]
path = "./rust/"
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
CARGO_REMOVE = '{{ .CargoFeatures }}'
CARGO_PATCH = """
{{ .CargoFeatures }} = {package = "libp2p", git = "https://{{ or $.Env.GitTarget "github.com/libp2p/rust-libp2p" }}", rev = "{{ $.Env.GitReference }}", default_features = false, features = [ "websocket", "mplex", "yamux", "tcp-async-io", "ping", "noise", "dns-async-std" ], version = "0.47.0", optional = true}
"""
{{ end }}
{{ end }}
{{ end }}
{{ end }}

View File

@ -0,0 +1,39 @@
[master]
GoVersion = '1.18'
Modfile = "go.v0.21.mod"
Selector = 'v0.21'
[custom]
GoVersion = '1.18'
Modfile = "go.v0.21.mod"
Selector = 'v0.21'
[[groups]]
Id = "v0.11"
GoVersion = '1.14'
Modfile = "go.v0.11.mod"
Selector = 'v0.11'
[[groups]]
Id = "v0.17"
GoVersion = '1.16'
Modfile = "go.v0.17.mod"
Selector = 'v0.17'
[[groups]]
Id = "v0.19"
GoVersion = '1.17'
Modfile = "go.v0.19.mod"
Selector = 'v0.19'
[[groups]]
Id = "v0.20"
GoVersion = '1.18'
Modfile = "go.v0.20.mod"
Selector = 'v0.20'
[[groups]]
Id = "v0.21"
GoVersion = '1.18'
Modfile = "go.v0.21.mod"
Selector = 'v0.21'

View File

@ -0,0 +1,44 @@
[metadata]
name = "rust-cross-versions-{{ $.Env.GitReference }}"
[global]
plan = "libp2p/ping/rust"
case = "ping"
builder = "docker:generic"
runner = "local:docker"
concurrent_builds = 1
{{ with (load_resource "./rust.toml" ) }}
{{ range .groups }}
[[groups]]
id = "{{ .Id }}"
instances = { count = 1 }
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
{{ end }}
{{ with .master }}
[[groups]]
id = "master"
instances = { count = 1 }
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
{{ end }}
{{ if $.Env.GitReference }}
{{ with .custom }}
[[groups]]
id = "custom"
instances = { count = 1 }
[groups.build_config.build_args]
CARGO_FEATURES = '{{ .CargoFeatures }}'
CARGO_REMOVE = '{{ .CargoFeatures }}'
CARGO_PATCH = """
{{ .CargoFeatures }} = {package = "libp2p", git = "https://{{ or $.Env.GitTarget "github.com/libp2p/rust-libp2p" }}", rev = "{{ $.Env.GitReference }}", default_features = false, features = [ "websocket", "mplex", "yamux", "tcp-async-io", "ping", "noise", "dns-async-std" ], version = "0.47.0", optional = true}
"""
{{ end }}
{{ end }}
{{ end }}

View File

@ -0,0 +1,17 @@
[[groups]]
Id = "v0.44.0"
CargoFeatures = 'libp2pv0440'
[[groups]]
Id = "v0.45.1"
CargoFeatures = 'libp2pv0450'
[[groups]]
Id = "v0.46.0"
CargoFeatures = 'libp2pv0460'
[master]
CargoFeatures = 'libp2pv0470'
[custom]
CargoFeatures = 'libp2pv0470'

23
ping/manifest.toml Normal file
View File

@ -0,0 +1,23 @@
name = "compatibility-rust-and-go"
[defaults]
builder = "docker:generic"
runner = "local:docker"
[builders."docker:generic"]
enabled = true
[builders."docker:go"]
enabled = true
[runners."local:docker"]
enabled = true
[[testcases]]
name = "ping"
instances = { min = 2, max = 10000, default = 5 }
[testcases.params]
secure_channel = { type = "enum", desc = "secure channel used", values = ["noise"], default = "noise" }
max_latency_ms = { type = "int", desc = "maximum value for random local link latency", unit = "ms", default = 1000 }
iterations = { type = "int", desc = "number of ping iterations we'll run against each peer", unit = "count", default = 5 }

1
ping/rust/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

4081
ping/rust/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

26
ping/rust/Cargo.toml Normal file
View File

@ -0,0 +1,26 @@
[package]
edition = "2021"
name = "testplan"
version = "0.1.0"
[dependencies]
async-std = {version = "1.10", features = ["attributes", "tokio1"]}
env_logger = "0.9.0"
if-addrs = "0.7.0"
ipnetwork = {version = "0.19.0", default-features = false, features = ["serde"]}
log = "0.4"
rand = "0.8"
serde = {version = "1", features = ["derive"]}
serde_json = "1"
soketto = "0.7.1"
testground = {git = "https://github.com/testground/sdk-rust", branch = "master", version = "0.4.0"}
thiserror = "1"
tokio = { version = "1", default-features = false, features = ["sync", "rt-multi-thread", "macros", "net"] }
tokio-stream = { version = "0.1", default-features = false, features = [] }
tokio-util = { version = "0.7", default-features = false, features = ["compat"] }
futures = "0.3.1"
libp2pv0440 = {package = "libp2p", default_features = false, features = [ "websocket", "mplex", "yamux", "tcp-async-io", "ping", "noise", "dns-async-std" ], version = "0.44.0", optional = true}
libp2pv0450 = {package = "libp2p", default_features = false, features = [ "websocket", "mplex", "yamux", "tcp-async-io", "ping", "noise", "dns-async-std" ], version = "0.45.0", optional = true}
libp2pv0460 = {package = "libp2p", default_features = false, features = [ "websocket", "mplex", "yamux", "tcp-async-io", "ping", "noise", "dns-async-std" ], version = "0.46.0", optional = true}
libp2pv0470 = {package = "libp2p", git = "https://github.com/libp2p/rust-libp2p", branch = "master", default_features = false, features = [ "websocket", "mplex", "yamux", "tcp-async-io", "ping", "noise", "dns-async-std" ], version = "0.47.0", optional = true}

46
ping/rust/Dockerfile Normal file
View File

@ -0,0 +1,46 @@
FROM rust:1.62-bullseye as builder
WORKDIR /usr/src/testplan
RUN apt-get update && apt-get install -y cmake protobuf-compiler
ARG PLAN_PATH="./"
# Cache dependencies between test runs, see testground examples.
RUN mkdir -p ./plan/src/
RUN echo "fn main() { println!(\"If you see this message, you may want to clean up the target directory or the Docker build cache.\") }" > ./plan/src/main.rs
COPY ./plan/${PLAN_PATH}/Cargo.lock ./plan/${PLAN_PATH}/Cargo.toml ./plan/
RUN cd ./plan/ && \
cargo update --dry-run && \
cargo fetch && \
# use a default feature to rely on docker caching.
cargo build --release --features "libp2pv0450"
ARG CARGO_PATCH=""
ARG CARGO_REMOVE=""
RUN if [ ! -z "${CARGO_REMOVE}" ]; then sed -i "s/^${CARGO_REMOVE}.*//" ./plan/Cargo.toml; fi
RUN echo "${CARGO_PATCH}" >> ./plan/Cargo.toml
# Backup Cargo file to preserve patches.
RUN cp ./plan/Cargo.toml ./plan/Cargo.lock /tmp/
COPY ./plan/${PLAN_PATH} ./plan
# This is in order to make sure `main.rs`s mtime timestamp is updated to avoid the dummy `main`
# remaining in the release binary.
# https://github.com/rust-lang/cargo/issues/9598
RUN touch ./plan/src/main.rs
RUN mv /tmp/Cargo.toml /tmp/Cargo.lock ./plan
ARG CARGO_FEATURES=""
RUN cd ./plan/ && \
cargo build --release --features="${CARGO_FEATURES}"
FROM debian:bullseye-slim
COPY --from=builder /usr/src/testplan/plan/target/release/testplan /usr/local/bin/testplan
EXPOSE 6060
ENV RUST_BACKTRACE=1
ENTRYPOINT ["testplan"]

19
ping/rust/manifest.toml Normal file
View File

@ -0,0 +1,19 @@
name = "compatibility-rust"
[defaults]
builder = "docker:generic"
runner = "local:docker"
[builders."docker:generic"]
enabled = true
[runners."local:docker"]
enabled = true
[[testcases]]
name = "ping"
instances = { min = 2, max = 10000, default = 5 }
[testcases.params]
max_latency_ms = { type = "int", desc = "maximum value for random local link latency", unit = "ms", default = 1000 }
iterations = { type = "int", desc = "number of ping iterations we'll run against each peer", unit = "count", default = 5 }

230
ping/rust/src/main.rs Normal file
View File

@ -0,0 +1,230 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::str::FromStr;
use std::time::Duration;
use env_logger::Env;
use log::info;
use rand::Rng;
use testground::network_conf::{
FilterAction, LinkShape, NetworkConfiguration, RoutingPolicyType, DEFAULT_DATA_NETWORK,
};
pub mod libp2p {
#[cfg(all(feature = "libp2pv0470",))]
pub use libp2pv0470::*;
#[cfg(all(feature = "libp2pv0460",))]
pub use libp2pv0460::*;
#[cfg(all(feature = "libp2pv0450",))]
pub use libp2pv0450::*;
#[cfg(all(feature = "libp2pv0440",))]
pub use libp2pv0440::*;
}
use libp2p::futures::future::ready;
use libp2p::futures::{FutureExt, StreamExt};
use libp2p::swarm::{Swarm, SwarmEvent};
use libp2p::{development_transport, identity, multiaddr::Protocol, ping, Multiaddr, PeerId};
const LISTENING_PORT: u16 = 1234;
#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let client = testground::client::Client::new_and_init().await?;
let mut swarm = {
let local_key = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_key.public());
info!("Local peer id: {:?}", local_peer_id);
Swarm::new(
development_transport(local_key).await?,
ping::Behaviour::new(
ping::Config::new()
.with_interval(Duration::from_secs(10))
.with_keep_alive(true),
),
local_peer_id,
)
};
let local_addr: Multiaddr = {
let ip_addr = match if_addrs::get_if_addrs()
.unwrap()
.into_iter()
.find(|iface| iface.name == "eth1")
.unwrap()
.addr
.ip()
{
std::net::IpAddr::V4(addr) => addr,
std::net::IpAddr::V6(_) => unimplemented!(),
};
Multiaddr::empty()
.with(Protocol::Ip4(ip_addr))
.with(Protocol::Tcp(LISTENING_PORT))
};
info!(
"Test instance, listening for incoming connections on: {:?}.",
local_addr
);
swarm.listen_on(local_addr.clone())?;
match swarm.next().await.unwrap() {
SwarmEvent::NewListenAddr { address, .. } if address == local_addr => {}
e => panic!("Unexpected event {:?}", e),
}
let mut address_stream = client
.subscribe("peers")
.await
.take(client.run_parameters().test_instance_count as usize)
.map(|a| {
let value = a.unwrap();
let addr = value["Addrs"][0].as_str().unwrap();
Multiaddr::from_str(addr).unwrap()
})
// Note: we sidestep simultaneous connect issues by ONLY connecting to peers
// who published their addresses before us (this is enough to dedup and avoid
// two peers dialling each other at the same time).
//
// We can do this because sync service pubsub is ordered.
.take_while(|a| ready(a != &local_addr));
let payload = serde_json::json!({
"ID": swarm.local_peer_id().to_string(),
"Addrs": [
local_addr.to_string(),
],
});
client.publish("peers", Cow::Owned(payload)).await?;
while let Some(addr) = address_stream.next().await {
swarm.dial(addr).unwrap();
}
// Otherwise the testground background task gets blocked sending
// subscription upgrades to the backpressured channel.
drop(address_stream);
info!("Wait to connect to each peer.");
let mut connected = HashSet::new();
while connected.len() < client.run_parameters().test_instance_count as usize - 1 {
let event = swarm.next().await.unwrap();
info!("Event: {:?}", event);
if let SwarmEvent::ConnectionEstablished { peer_id, .. } = event {
connected.insert(peer_id);
}
}
signal_wait_and_drive_swarm(&client, &mut swarm, "connected".to_string()).await?;
ping(&client, &mut swarm, "initial".to_string()).await?;
let iterations: usize = client
.run_parameters()
.test_instance_params
.get("iterations")
.unwrap()
.parse()
.unwrap();
let max_latency_ms: u64 = client
.run_parameters()
.test_instance_params
.get("max_latency_ms")
.unwrap()
.parse()
.unwrap();
for i in 1..iterations + 1 {
client.record_message(format!("⚡️ ITERATION ROUND {}", i));
let latency = Duration::from_millis(rand::thread_rng().gen_range(0..max_latency_ms))
.as_nanos()
.try_into()
.unwrap();
let network_conf = NetworkConfiguration {
network: DEFAULT_DATA_NETWORK.to_owned(),
ipv4: None,
ipv6: None,
enable: true,
default: LinkShape {
latency,
jitter: 0,
bandwidth: 0,
filter: FilterAction::Accept,
loss: 0.0,
corrupt: 0.0,
corrupt_corr: 0.0,
reorder: 0.0,
reorder_corr: 0.0,
duplicate: 0.0,
duplicate_corr: 0.0,
},
rules: None,
callback_state: format!("network-configured-{}", i),
callback_target: Some(client.run_parameters().test_instance_count),
routing_policy: RoutingPolicyType::AllowAll,
};
client.configure_network(network_conf).await.unwrap();
ping(&client, &mut swarm, format!("done-{}", i)).await?;
}
client.record_success().await?;
Ok(())
}
async fn ping(
client: &testground::client::Client,
swarm: &mut Swarm<ping::Behaviour>,
tag: String,
) -> Result<(), Box<dyn std::error::Error>> {
info!("Wait to receive ping from each peer.");
let mut pinged = HashSet::new();
while pinged.len() < client.run_parameters().test_instance_count as usize - 1 {
let event = swarm.next().await.unwrap();
info!("Event: {:?}", event);
if let SwarmEvent::Behaviour(ping::PingEvent {
peer,
result: Ok(ping::PingSuccess::Ping { .. }),
}) = event
{
pinged.insert(peer);
}
}
signal_wait_and_drive_swarm(client, swarm, tag).await
}
async fn signal_wait_and_drive_swarm(
client: &testground::client::Client,
swarm: &mut Swarm<ping::Behaviour>,
tag: String,
) -> Result<(), Box<dyn std::error::Error>> {
info!(
"Signal and wait for all peers to signal being done with \"{}\".",
tag
);
swarm
.take_until(
client
.signal_and_wait(tag, client.run_parameters().test_instance_count)
.boxed_local(),
)
.map(|event| info!("Event: {:?}", event))
.collect::<Vec<()>>()
.await;
Ok(())
}