Skip to content

Commit f9af5a0

Browse files
authored
Rust dial test (#39)
1 parent 9ca379b commit f9af5a0

File tree

8 files changed

+283
-4
lines changed

8 files changed

+283
-4
lines changed

.github/workflows/test.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Run tests
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- main
8+
pull_request:
9+
branches:
10+
- main
11+
12+
jobs:
13+
test:
14+
if: github.repository_owner == 'viamrobotics'
15+
runs-on: [self-hosted, x64]
16+
container:
17+
image: ghcr.io/viamrobotics/canon:amd64
18+
steps:
19+
- name: Checkout PR/Push/Workflow Dispatch
20+
uses: actions/checkout@v3
21+
- name: Setup Rust toolchain
22+
uses: actions-rs/toolchain@v1
23+
with:
24+
toolchain: stable
25+
- name: Run tests
26+
run: |
27+
apt-get -y install lsof
28+
make test

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@ target/
33
**/*.rs.bk
44

55
*.DS_Store
6+
7+
# make tools bin
8+
bin/
9+
10+
# goutils
11+
tests/goutils/

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,14 @@ tower-http = { version = "0.3.3", features = ["add-extension","auth","propagate-
4444
tracing = {version = "0.1.34"}
4545
tracing-subscriber = {version = "0.3.11", features = ["env-filter"]}
4646
webpki-roots = "0.21.1"
47-
webrtc = "0.7.1"
47+
# TODO: We are using a commit hash to include a bug fix that has not yet been
48+
# released in a crate. Once the new crate is released, please use that instead
49+
# of the git revision below. As of this comment the latest version is `0.7.1`.
50+
webrtc = { git = "https://github.com/webrtc-rs/webrtc.git", rev = "5aa49c03a183a610b44fe01e9531508e4fddecb1" }
4851

52+
[dev-dependencies]
53+
async-stream = "0.3.3"
54+
env_logger = "0.9.0"
4955

5056
[build-dependencies]
5157
tonic-build = {version = "0.7.2",features = ["prost", "compression"]}

Makefile

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1+
BUF_BIN="`pwd`/bin"
2+
PATH_WITH_TOOLS="${BUF_BIN}:${PATH}"
3+
14
all: build build-example
25
build:
36
cargo build
47
build-example:
58
cd examples/ && cargo build
69
buf-clean:
710
find src/gen -type f \( -iname "*.rs" ! -iname "mod.rs" \) -delete
8-
buf: buf-clean
9-
buf generate buf.build/viamrobotics/goutils --template buf.gen.yaml
10-
buf generate buf.build/googleapis/googleapis --template buf.gen.yaml --path google/rpc --path google/api
11+
buf-install:
12+
./etc/install_buf.sh $(BUF_BIN)
13+
buf: buf-install buf-clean
14+
PATH=${PATH_WITH_TOOLS} buf generate buf.build/viamrobotics/goutils --template buf.gen.yaml
15+
PATH=${PATH_WITH_TOOLS} buf generate buf.build/googleapis/googleapis --template buf.gen.yaml --path google/rpc --path google/api
16+
tests/goutils:
17+
git clone --depth=1 https://github.com/viamrobotics/goutils.git tests/goutils
18+
test: buf tests/goutils build
19+
./etc/test.sh
20+
test-server: tests/goutils
21+
./etc/run_echo_server.sh 8081

etc/install_buf.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
# Substitute BIN for your bin directory.
4+
# Substitute VERSION for the current released version.
5+
6+
if [[ -z "$1" ]]; then
7+
echo "please provide an installation direction"
8+
exit 1
9+
fi
10+
11+
BIN="$1"
12+
VERSION="1.16.0"
13+
14+
mkdir -p "$BIN"
15+
curl -sSL \
16+
"https://github.com/bufbuild/buf/releases/download/v${VERSION}/buf-$(uname -s)-$(uname -m)" \
17+
-o "${BIN}/buf"
18+
chmod +x "${BIN}/buf"

etc/run_echo_server.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
cd tests/goutils/rpc/examples/echo || exit 1
4+
5+
go run server/cmd/main.go -instance-name="localhost:$1" "$1"

etc/test.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
SERVER_PORT=8081
4+
5+
if lsof -i ":$SERVER_PORT" | grep -q LISTEN; then
6+
echo "port :$SERVER_PORT is in use"
7+
exit 1
8+
fi
9+
10+
./etc/run_echo_server.sh "$SERVER_PORT" &
11+
12+
while ! lsof -i ":$SERVER_PORT" | grep -q LISTEN; do
13+
sleep 0.1
14+
done
15+
16+
SERVER_PORT=$SERVER_PORT cargo test --test "*"
17+
result=$?
18+
19+
kill "$(lsof -t -i:$SERVER_PORT)"
20+
21+
exit $result

tests/echo_test.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/// Tests unary, server, and bidi streaming with simple echo requests. To run, simply
2+
/// update the credentials and uri as necessary.
3+
use anyhow::Result;
4+
use std::env;
5+
use std::sync::{Arc, RwLock};
6+
use viam_rust_utils::gen::proto::rpc::examples::echo::v1::echo_service_client::EchoServiceClient;
7+
use viam_rust_utils::gen::proto::rpc::examples::echo::v1::{
8+
EchoBiDiRequest, EchoMultipleRequest, EchoRequest,
9+
};
10+
use viam_rust_utils::rpc::dial;
11+
12+
async fn dial_direct() -> Result<dial::ViamChannel> {
13+
let port = env::var("SERVER_PORT").unwrap().to_owned();
14+
let uri = ["localhost:".to_string(), port].join("");
15+
16+
dial::DialOptions::builder()
17+
.uri(&uri)
18+
.without_credentials()
19+
.insecure()
20+
.disable_webrtc()
21+
.connect()
22+
.await
23+
}
24+
25+
#[tokio::test]
26+
async fn test_dial_direct_unary() -> Result<()> {
27+
let c = dial_direct().await?;
28+
29+
let mut service = EchoServiceClient::new(c);
30+
let echo_request = EchoRequest {
31+
message: "hi".to_string(),
32+
};
33+
let resp = service.echo(echo_request).await?.into_inner();
34+
assert_eq!(resp.message, "hi".to_string());
35+
36+
Ok(())
37+
}
38+
39+
#[tokio::test]
40+
async fn test_dial_direct_server_stream() -> Result<()> {
41+
let c = dial_direct().await?;
42+
43+
let mut service = EchoServiceClient::new(c);
44+
let multi_echo_request = EchoMultipleRequest {
45+
message: "hello?".to_string(),
46+
};
47+
48+
let mut expected = vec!["h", "e", "l", "l", "o", "?"];
49+
expected.reverse();
50+
51+
let mut resp = service
52+
.echo_multiple(multi_echo_request)
53+
.await?
54+
.into_inner();
55+
while let Some(resp) = resp.message().await? {
56+
assert_eq!(resp.message, expected.pop().unwrap().to_string())
57+
}
58+
assert!(expected.is_empty());
59+
60+
Ok(())
61+
}
62+
63+
#[tokio::test]
64+
async fn test_dial_direct_bidi() -> Result<()> {
65+
let c = dial_direct().await?;
66+
67+
let received = Arc::new(RwLock::new(0));
68+
let received_async = Arc::clone(&received);
69+
70+
let bidi_stream = async_stream::stream! {
71+
for i in 0..3 {
72+
loop {
73+
// We need to wait a small amount of time between each request/response count
74+
// check, otherwise we lock up the main thread.
75+
let sleep_time = std::time::Duration::from_millis(10);
76+
tokio::time::sleep(sleep_time).await;
77+
78+
// Wait until we have received one response for each request before sending the
79+
// next request. This allows requests/response to be interleaved.
80+
let value = received_async.read().unwrap();
81+
if *value == i {
82+
break;
83+
}
84+
}
85+
86+
let request =
87+
EchoBiDiRequest {
88+
message: i.to_string()
89+
};
90+
yield request;
91+
}
92+
};
93+
94+
let mut service = EchoServiceClient::new(c);
95+
let mut bidi_resp = service.echo_bi_di(bidi_stream).await?.into_inner();
96+
97+
for i in 0..3 {
98+
let resp = bidi_resp.message().await?.unwrap();
99+
assert_eq!(resp.message, i.to_string());
100+
101+
let mut count = received.write().unwrap();
102+
*count += 1;
103+
drop(count);
104+
}
105+
106+
Ok(())
107+
}
108+
109+
async fn dial_webrtc() -> Result<dial::ViamChannel> {
110+
let port = env::var("SERVER_PORT").unwrap().to_owned();
111+
let uri = ["localhost:".to_string(), port].join("");
112+
113+
dial::DialOptions::builder()
114+
.uri(&uri)
115+
.without_credentials()
116+
.insecure()
117+
.connect()
118+
.await
119+
}
120+
121+
#[tokio::test]
122+
async fn test_dial_webrtc_unary() -> Result<()> {
123+
let c = dial_webrtc().await?;
124+
125+
let mut service = EchoServiceClient::new(c);
126+
let echo_request = EchoRequest {
127+
message: "hi".to_string(),
128+
};
129+
let resp = service.echo(echo_request).await?.into_inner();
130+
assert_eq!(resp.message, "hi".to_string());
131+
132+
Ok(())
133+
}
134+
135+
#[tokio::test]
136+
async fn test_dial_webrtc_server_stream() -> Result<()> {
137+
let c = dial_webrtc().await?;
138+
139+
let mut service = EchoServiceClient::new(c);
140+
let multi_echo_request = EchoMultipleRequest {
141+
message: "hello?".to_string(),
142+
};
143+
144+
let mut expected = vec!["h", "e", "l", "l", "o", "?"];
145+
expected.reverse();
146+
147+
let mut resp = service
148+
.echo_multiple(multi_echo_request)
149+
.await?
150+
.into_inner();
151+
while let Some(resp) = resp.message().await? {
152+
assert_eq!(resp.message, expected.pop().unwrap().to_string())
153+
}
154+
assert!(expected.is_empty());
155+
156+
Ok(())
157+
}
158+
159+
#[tokio::test]
160+
async fn test_dial_webrtc_bidi() -> Result<()> {
161+
let c = dial_webrtc().await?;
162+
163+
// TODO(RSDK-2414): ideally we should mix the timing of our requests and responses to ensure
164+
// that we truly support bi-directionality.
165+
let bidi_stream = async_stream::stream! {
166+
for i in 0..3 {
167+
let request =
168+
EchoBiDiRequest {
169+
message: i.to_string()
170+
};
171+
yield request;
172+
}
173+
};
174+
175+
let mut service = EchoServiceClient::new(c);
176+
let mut bidi_resp = service.echo_bi_di(bidi_stream).await?.into_inner();
177+
178+
for i in 0..3 {
179+
let resp = bidi_resp.message().await?.unwrap();
180+
assert_eq!(resp.message, i.to_string());
181+
}
182+
183+
Ok(())
184+
}

0 commit comments

Comments
 (0)