cleanup integration and e2e tests
Signed-off-by: Rajat Jindal <rajatjindal83@gmail.com>
This commit is contained in:
parent
77985ccb79
commit
0d48649d29
|
@ -117,9 +117,9 @@ jobs:
|
|||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
|
||||
- name: Cargo E2E Tests
|
||||
- name: Fermyon Platform Integration Tests
|
||||
run: |
|
||||
make test-e2e
|
||||
make test-fermyon-platform
|
||||
env:
|
||||
RUST_LOG: spin=trace
|
||||
CARGO_INCREMENTAL: 0
|
||||
|
@ -166,10 +166,8 @@ jobs:
|
|||
name: spin-ubuntu-latest
|
||||
path: target/release/
|
||||
|
||||
- name: Build e2e tests image
|
||||
run: |
|
||||
docker build -t spin-e2e-tests -f e2e-tests.Dockerfile .
|
||||
- name: Run e2e tests
|
||||
run: |
|
||||
chmod +x `pwd`/target/release/spin
|
||||
docker compose -f e2e-tests-docker-compose.yml run -v `pwd`/target/release/spin:/usr/local/bin/spin e2e-tests
|
||||
export E2E_VOLUME_MOUNT="-v `pwd`/target/release/spin:/usr/local/bin/spin"
|
||||
make test-spin-up
|
||||
|
|
|
@ -92,7 +92,7 @@ outbound-redis-tests = []
|
|||
config-provider-tests = []
|
||||
outbound-pg-tests = []
|
||||
outbound-mysql-tests = []
|
||||
new-e2e-tests = []
|
||||
fermyon-platform = []
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
|
|
40
Makefile
40
Makefile
|
@ -2,6 +2,24 @@ LOG_LEVEL ?= spin=trace
|
|||
CERT_NAME ?= local
|
||||
SPIN_DOC_NAME ?= new-doc.md
|
||||
|
||||
ARCH = $(shell uname -p)
|
||||
|
||||
## dependencies for e2e-tests
|
||||
E2E_VOLUME_MOUNT ?=
|
||||
E2E_BUILD_SPIN ?= false
|
||||
E2E_TESTS_DOCKERFILE ?= e2e-tests.Dockerfile
|
||||
MYSQL_IMAGE ?= mysql:8.0.22
|
||||
REDIS_IMAGE ?= redis:7.0.8-alpine3.17
|
||||
POSTGRES_IMAGE ?= postgres:14.7-alpine
|
||||
|
||||
## overrides for aarch64
|
||||
ifneq ($(ARCH),x86_64)
|
||||
MYSQL_IMAGE = arm64v8/mysql:8.0.32
|
||||
REDIS_IMAGE = arm64v8/redis:6.0-alpine3.17
|
||||
POSTGRES_IMAGE = arm64v8/postgres:14.7
|
||||
E2E_TESTS_DOCKERFILE = e2e-tests-aarch64.Dockerfile
|
||||
endif
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
cargo build --release
|
||||
|
@ -28,10 +46,16 @@ test-unit:
|
|||
test-integration:
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --no-fail-fast -- --skip spinup_tests --skip cloud_tests --nocapture
|
||||
|
||||
.PHONY: test-e2e
|
||||
test-e2e:
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --features e2e-tests --no-fail-fast -- integration_tests::test_dependencies --skip spinup_tests --skip cloud_tests --nocapture
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --features e2e-tests --no-fail-fast -- --skip integration_tests::test_dependencies --skip spinup_tests --skip cloud_tests --nocapture
|
||||
.PHONY: test-fermyon-platform
|
||||
test-fermyon-platform:
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --features fermyon-platform --no-fail-fast -- integration_tests::test_dependencies --skip spinup_tests --nocapture
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --features fermyon-platform --no-fail-fast -- --skip integration_tests::test_dependencies --skip spinup_tests --nocapture
|
||||
|
||||
.PHONY: test-spin-up
|
||||
test-spin-up:
|
||||
docker build -t spin-e2e-tests --build-arg BUILD_SPIN=$(E2E_BUILD_SPIN) -f $(E2E_TESTS_DOCKERFILE) .
|
||||
REDIS_IMAGE=$(REDIS_IMAGE) MYSQL_IMAGE=$(MYSQL_IMAGE) POSTGRES_IMAGE=$(POSTGRES_IMAGE) \
|
||||
docker compose -f e2e-tests-docker-compose.yml run $(E2E_VOLUME_MOUNT) e2e-tests
|
||||
|
||||
.PHONY: test-outbound-redis
|
||||
test-outbound-redis:
|
||||
|
@ -41,14 +65,6 @@ test-outbound-redis:
|
|||
test-config-provider:
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --features config-provider-tests --no-fail-fast -- integration_tests::config_provider_tests --nocapture
|
||||
|
||||
.PHONY: test-outbound-pg
|
||||
test-outbound-pg:
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --features outbound-pg-tests --no-fail-fast -- --nocapture
|
||||
|
||||
.PHONY: test-outbound-mysql
|
||||
test-outbound-mysql:
|
||||
RUST_LOG=$(LOG_LEVEL) cargo test --test integration --features outbound-mysql-tests --no-fail-fast -- --nocapture
|
||||
|
||||
.PHONY: test-sdk-go
|
||||
test-sdk-go:
|
||||
$(MAKE) -C sdk/go test
|
||||
|
|
2
build.rs
2
build.rs
|
@ -12,7 +12,6 @@ const RUST_HTTP_INTEGRATION_ENV_TEST: &str = "tests/http/headers-env-routes-test
|
|||
const RUST_HTTP_INTEGRATION_KEY_VALUE_TEST: &str = "tests/http/key-value";
|
||||
const RUST_HTTP_VAULT_CONFIG_TEST: &str = "tests/http/vault-config-test";
|
||||
const RUST_OUTBOUND_REDIS_INTEGRATION_TEST: &str = "tests/outbound-redis/http-rust-outbound-redis";
|
||||
const RUST_OUTBOUND_PG_INTEGRATION_TEST: &str = "tests/outbound-pg/http-rust-outbound-pg";
|
||||
|
||||
fn main() {
|
||||
let mut config = vergen::Config::default();
|
||||
|
@ -75,7 +74,6 @@ error: the `wasm32-wasi` target is not installed
|
|||
cargo_build(RUST_HTTP_INTEGRATION_KEY_VALUE_TEST);
|
||||
cargo_build(RUST_HTTP_VAULT_CONFIG_TEST);
|
||||
cargo_build(RUST_OUTBOUND_REDIS_INTEGRATION_TEST);
|
||||
cargo_build(RUST_OUTBOUND_PG_INTEGRATION_TEST);
|
||||
}
|
||||
|
||||
fn build_wasm_test_program(name: &'static str, root: &'static str) {
|
||||
|
|
|
@ -2,9 +2,10 @@ use crate::controller::{AppInstance, Controller};
|
|||
use crate::metadata_extractor::AppMetadata;
|
||||
use crate::spin;
|
||||
use crate::utils;
|
||||
use anyhow::Result;
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use std::process::Output;
|
||||
use std::time::Duration;
|
||||
use tokio::io::BufReader;
|
||||
|
||||
pub struct SpinUp {}
|
||||
|
@ -61,7 +62,27 @@ impl Controller for SpinUp {
|
|||
|
||||
if trigger_type == "http" {
|
||||
// ensure the server is accepting requests before continuing.
|
||||
utils::wait_tcp(&address, &mut child, "spin").await?;
|
||||
match utils::wait_tcp(&address, &mut child, "spin").await {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
let stdout = child.stdout.take().expect("stdout handle not found");
|
||||
let stdout_stream = BufReader::new(stdout);
|
||||
let stdout_logs =
|
||||
utils::get_output_from_stdout(Some(stdout_stream), Duration::from_secs(2))
|
||||
.await?;
|
||||
|
||||
let stderr = child.stderr.take().expect("stderr handle not found");
|
||||
let stderr_stream = BufReader::new(stderr);
|
||||
let stderr_logs =
|
||||
utils::get_output_from_stderr(Some(stderr_stream), Duration::from_secs(2))
|
||||
.await?;
|
||||
return Err(anyhow!(
|
||||
"error running spin up.\nstdout {:?}\nstderr: {:?}\n",
|
||||
stdout_logs,
|
||||
stderr_logs
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let stdout = child
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::path::PathBuf;
|
||||
use std::str;
|
||||
use std::{
|
||||
|
@ -75,17 +75,19 @@ pub async fn wait_tcp(url: &str, process: &mut tokio::process::Child, target: &s
|
|||
let mut wait_count = 0;
|
||||
loop {
|
||||
if wait_count >= 240 {
|
||||
panic!(
|
||||
return Err(anyhow!(
|
||||
"Ran out of retries waiting for {} to start on URL {}",
|
||||
target, url
|
||||
);
|
||||
target,
|
||||
url
|
||||
));
|
||||
}
|
||||
|
||||
if let Ok(Some(_)) = process.try_wait() {
|
||||
panic!(
|
||||
return Err(anyhow!(
|
||||
"Process exited before starting to serve {} to start on URL {}",
|
||||
target, url
|
||||
);
|
||||
target,
|
||||
url
|
||||
));
|
||||
}
|
||||
|
||||
match TcpStream::connect(&url).await {
|
||||
|
@ -195,7 +197,13 @@ pub async fn get_output_from_stdout(
|
|||
Err(_) => break,
|
||||
Ok(result) => match result {
|
||||
Err(_) => break,
|
||||
Ok(line) => output.push(line.unwrap()),
|
||||
Ok(line) => {
|
||||
if line.is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
output.push(line.unwrap())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +229,13 @@ pub async fn get_output_from_stderr(
|
|||
Err(_) => break,
|
||||
Ok(result) => match result {
|
||||
Err(_) => break,
|
||||
Ok(line) => output.push(line.unwrap()),
|
||||
Ok(line) => {
|
||||
if line.is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
output.push(line.unwrap())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,16 +56,15 @@ COPY . .
|
|||
|
||||
# spin
|
||||
RUN if [ "${BUILD_SPIN}" != "true" ]; then \
|
||||
wget https://github.com/fermyon/spin/releases/download/${SPIN_VERSION}/spin-${SPIN_VERSION}-linux-aarch64.tar.gz && \
|
||||
tar -xvf spin-${SPIN_VERSION}-linux-aarch64.tar.gz && \
|
||||
ls -ltr && \
|
||||
mv spin /usr/local/bin/spin; \
|
||||
wget https://github.com/fermyon/spin/releases/download/${SPIN_VERSION}/spin-${SPIN_VERSION}-linux-aarch64.tar.gz && \
|
||||
tar -xvf spin-${SPIN_VERSION}-linux-aarch64.tar.gz && \
|
||||
ls -ltr && \
|
||||
mv spin /usr/local/bin/spin; \
|
||||
else \
|
||||
cargo build --release && \
|
||||
cp target/release/spin /usr/local/bin/spin; \
|
||||
cargo build --release && \
|
||||
cp target/release/spin /usr/local/bin/spin; \
|
||||
fi
|
||||
|
||||
RUN spin --version
|
||||
|
||||
|
||||
CMD cargo test spinup_tests --features new-e2e-tests --no-fail-fast -- --nocapture
|
||||
|
|
|
@ -14,6 +14,18 @@ services:
|
|||
MYSQL_USER: spin
|
||||
MYSQL_PASSWORD: spin
|
||||
|
||||
postgres:
|
||||
image: ${POSTGRES_IMAGE:-postgres:14.7-alpine}
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
- POSTGRES_DB=spin_dev
|
||||
ports:
|
||||
- '5432:5432'
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
redis:
|
||||
image: ${REDIS_IMAGE:-redis:7.0.8-alpine3.17}
|
||||
ports:
|
||||
|
@ -24,8 +36,17 @@ services:
|
|||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
- postgres
|
||||
image: spin-e2e-tests
|
||||
entrypoint: cargo test spinup_tests --features new-e2e-tests --no-fail-fast -- --nocapture
|
||||
entrypoint: cargo test spinup_tests --features e2e-tests --no-fail-fast -- --nocapture
|
||||
volumes:
|
||||
- target_cache:/e2e-tests/target
|
||||
- cargo_registry_cache:/usr/local/cargo/registry
|
||||
- cargo_git_cache:/usr/local/cargo/git
|
||||
|
||||
volumes:
|
||||
db_data: {}
|
||||
postgres_data: {}
|
||||
cargo_registry_cache: {}
|
||||
cargo_git_cache: {}
|
||||
target_cache: {}
|
|
@ -16,28 +16,15 @@ The goal of these tests is to ensure that spin continues to work with existing a
|
|||
|
||||
```
|
||||
## go to root dir of the project, e2e-tests.Dockerfile is located there
|
||||
docker build -t spin-e2e-tests -f e2e-tests.Dockerfile .
|
||||
docker compose -f e2e-tests-docker-compose.yml run e2e-tests
|
||||
```
|
||||
|
||||
## How to run e2e tests on aarch64
|
||||
```
|
||||
## go to root dir of the project, e2e-tests-aarch64.Dockerfile is located there
|
||||
docker build -t spin-e2e-tests -f e2e-tests-aarch64.Dockerfile .
|
||||
MYSQL_IMAGE=arm64v8/mysql:8.0.32 REDIS_IMAGE=arm64v8/redis:6.0-alpine3.17 docker compose \
|
||||
-f e2e-tests-docker-compose.yml run \
|
||||
e2e-tests
|
||||
make test-spin-up
|
||||
```
|
||||
|
||||
## How to use `spin` binary with your local changes
|
||||
|
||||
By default tests use the canary build of `spin` downloaded at docker image creation time. If you want to test it with your changes, you can use `--build-arg BUILD_SPIN=true`
|
||||
By default, tests use the canary build of `spin` downloaded at the docker image creation time. If you want to test it with your changes, you can use the environment variable E2E_BUILD_SPIN=true
|
||||
|
||||
```
|
||||
docker build --build-arg BUILD_SPIN=true -t spin-e2e-tests -f e2e-tests.Dockerfile .
|
||||
docker compose \
|
||||
-f e2e-tests-docker-compose.yml run \
|
||||
e2e-tests
|
||||
E2E_BUILD_SPIN=true make test-spin-up
|
||||
```
|
||||
|
||||
## Important files and their function
|
||||
|
|
|
@ -22,8 +22,8 @@ mod integration_tests {
|
|||
const SPIN_BINARY: &str = "./target/debug/spin";
|
||||
|
||||
// This module consist of all integration tests that require dependencies such as bindle-server, nomad, and Hippo.Web to be installed.
|
||||
#[cfg(feature = "e2e-tests")]
|
||||
mod e2e_tests {
|
||||
#[cfg(feature = "fermyon-platform")]
|
||||
mod fermyon_platform {
|
||||
use super::*;
|
||||
use hyper::header::HeaderName;
|
||||
use std::path::PathBuf;
|
||||
|
@ -613,61 +613,6 @@ mod integration_tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "outbound-pg-tests")]
|
||||
mod outbound_pg_tests {
|
||||
use super::*;
|
||||
|
||||
const RUST_OUTBOUND_PG_INTEGRATION_TEST: &str = "tests/outbound-pg/http-rust-outbound-pg";
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_outbound_pg_rust_local() -> Result<()> {
|
||||
let s = SpinTestController::with_manifest(
|
||||
&format!(
|
||||
"{}/{}",
|
||||
RUST_OUTBOUND_PG_INTEGRATION_TEST, DEFAULT_MANIFEST_LOCATION
|
||||
),
|
||||
&[],
|
||||
&[],
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_status(&s, "/test_numeric_types", 200).await?;
|
||||
assert_status(&s, "/test_character_types", 200).await?;
|
||||
assert_status(&s, "/test_general_types", 200).await?;
|
||||
assert_status(&s, "/pg_backend_pid", 200).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "outbound-mysql-tests")]
|
||||
mod outbound_mysql_tests {
|
||||
use super::*;
|
||||
|
||||
const RUST_OUTBOUND_MYSQL_INTEGRATION_TEST: &str =
|
||||
"tests/outbound-mysql/http-rust-outbound-mysql";
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_outbound_mysql_rust_local() -> Result<()> {
|
||||
let s = SpinTestController::with_manifest(
|
||||
&format!(
|
||||
"{}/{}",
|
||||
RUST_OUTBOUND_MYSQL_INTEGRATION_TEST, DEFAULT_MANIFEST_LOCATION
|
||||
),
|
||||
&[],
|
||||
&[],
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_status(&s, "/test_numeric_types", 200).await?;
|
||||
assert_status(&s, "/test_character_types", 200).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "config-provider-tests")]
|
||||
mod config_provider_tests {
|
||||
use super::*;
|
||||
|
@ -847,7 +792,7 @@ mod integration_tests {
|
|||
}
|
||||
|
||||
// Unfortunately, this is a lot of duplicated code.
|
||||
#[cfg(feature = "e2e-tests")]
|
||||
#[cfg(feature = "fermyon-platform")]
|
||||
pub async fn with_bindle(
|
||||
id: &str,
|
||||
bindle_url: &str,
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
[package]
|
||||
name = "http-rust-outbound-mysql"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = [ "cdylib" ]
|
||||
|
||||
[dependencies]
|
||||
# Useful crate to handle errors.
|
||||
anyhow = "1"
|
||||
# Crate to simplify working with bytes.
|
||||
bytes = "1"
|
||||
# General-purpose crate with common HTTP types.
|
||||
http = "0.2"
|
||||
# The Spin SDK.
|
||||
spin-sdk = { path = "../../../sdk/rust" }
|
||||
# Crate that generates Rust Wasm bindings from a WebAssembly interface.
|
||||
wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "cb871cfa1ee460b51eb1d144b175b9aab9c50aba" }
|
||||
|
||||
[workspace]
|
|
@ -1,14 +0,0 @@
|
|||
spin_version = "1"
|
||||
authors = ["Fermyon Engineering <engineering@fermyon.com>"]
|
||||
name = "rust-outbound-mysql-example"
|
||||
trigger = { type = "http", base = "/" }
|
||||
version = "0.1.0"
|
||||
|
||||
[[component]]
|
||||
environment = { DB_URL = "mysql://spin:spin@127.0.0.1/spin_dev" }
|
||||
id = "outbound-mysql"
|
||||
source = "target/wasm32-wasi/release/http_rust_outbound_mysql.wasm"
|
||||
[component.trigger]
|
||||
route = "/..."
|
||||
[component.build]
|
||||
command = "cargo build --target wasm32-wasi --release"
|
|
@ -1,239 +0,0 @@
|
|||
#![allow(dead_code)]
|
||||
use anyhow::{anyhow, Result};
|
||||
use spin_sdk::{
|
||||
http::{Request, Response},
|
||||
http_component, mysql::{self, Decode},
|
||||
};
|
||||
|
||||
// The environment variable set in `spin.toml` that points to the
|
||||
// address of the Pg server that the component will write to
|
||||
const DB_URL_ENV: &str = "DB_URL";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct NumericRow {
|
||||
rtiny: i8,
|
||||
rsmall: i16,
|
||||
rmedium: i32,
|
||||
rint: i32,
|
||||
rbig: i64,
|
||||
rfloat: f32,
|
||||
rdouble: f64,
|
||||
rutiny: u8,
|
||||
rusmall: u16,
|
||||
rumedium: u32,
|
||||
ruint: u32,
|
||||
rubig: u64,
|
||||
rtinyint1: bool,
|
||||
rbool: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct CharacterRow {
|
||||
rvarchar: String,
|
||||
rtext: String,
|
||||
rchar: String,
|
||||
rbinary: Vec<u8>,
|
||||
rvarbinary: Vec<u8>,
|
||||
rblob: Vec<u8>
|
||||
}
|
||||
|
||||
#[http_component]
|
||||
fn process(req: Request) -> Result<Response> {
|
||||
match req.uri().path() {
|
||||
"/test_character_types" => test_character_types(req),
|
||||
"/test_numeric_types" => test_numeric_types(req),
|
||||
_ => Ok(http::Response::builder()
|
||||
.status(404)
|
||||
.body(Some("Not found".into()))?),
|
||||
}
|
||||
}
|
||||
|
||||
fn test_numeric_types(_req: Request) -> Result<Response> {
|
||||
let address = std::env::var(DB_URL_ENV)?;
|
||||
|
||||
let create_table_sql = r#"
|
||||
CREATE TEMPORARY TABLE test_numeric_types (
|
||||
rtiny TINYINT NOT NULL,
|
||||
rsmall SMALLINT NOT NULL,
|
||||
rmedium MEDIUMINT NOT NULL,
|
||||
rint INT NOT NULL,
|
||||
rbig BIGINT NOT NULL,
|
||||
rfloat FLOAT NOT NULL,
|
||||
rdouble DOUBLE NOT NULL,
|
||||
rutiny TINYINT UNSIGNED NOT NULL,
|
||||
rusmall SMALLINT UNSIGNED NOT NULL,
|
||||
rumedium MEDIUMINT UNSIGNED NOT NULL,
|
||||
ruint INT UNSIGNED NOT NULL,
|
||||
rubig BIGINT UNSIGNED NOT NULL,
|
||||
rtinyint1 TINYINT(1) NOT NULL,
|
||||
rbool BOOLEAN NOT NULL
|
||||
);
|
||||
"#;
|
||||
|
||||
mysql::execute(&address, create_table_sql, &[])?;
|
||||
|
||||
let insert_sql = r#"
|
||||
INSERT INTO test_numeric_types
|
||||
(rtiny, rsmall, rmedium, rint, rbig, rfloat, rdouble, rutiny, rusmall, rumedium, ruint, rubig, rtinyint1, rbool)
|
||||
VALUES
|
||||
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1);
|
||||
"#;
|
||||
|
||||
mysql::execute(&address, insert_sql, &[])?;
|
||||
|
||||
let sql = r#"
|
||||
SELECT
|
||||
rtiny,
|
||||
rsmall,
|
||||
rmedium,
|
||||
rint,
|
||||
rbig,
|
||||
rfloat,
|
||||
rdouble,
|
||||
rutiny,
|
||||
rusmall,
|
||||
rumedium,
|
||||
ruint,
|
||||
rubig,
|
||||
rtinyint1,
|
||||
rbool
|
||||
FROM test_numeric_types;
|
||||
"#;
|
||||
|
||||
let rowset = mysql::query(&address, sql, &[])?;
|
||||
|
||||
let column_summary = rowset
|
||||
.columns
|
||||
.iter()
|
||||
.map(format_col)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
let mut response_lines = vec![];
|
||||
|
||||
for row in rowset.rows {
|
||||
let rtiny = i8::decode(&row[0])?;
|
||||
let rsmall = i16::decode(&row[1])?;
|
||||
let rmedium = i32::decode(&row[2])?;
|
||||
let rint = i32::decode(&row[3])?;
|
||||
let rbig = i64::decode(&row[4])?;
|
||||
let rfloat = f32::decode(&row[5])?;
|
||||
let rdouble = f64::decode(&row[6])?;
|
||||
let rutiny = u8::decode(&row[7])?;
|
||||
let rusmall = u16::decode(&row[8])?;
|
||||
let rumedium = u32::decode(&row[9])?;
|
||||
let ruint = u32::decode(&row[10])?;
|
||||
let rubig = u64::decode(&row[11])?;
|
||||
let rtinyint1 = bool::decode(&row[12])?;
|
||||
let rbool = bool::decode(&row[13])?;
|
||||
|
||||
let row = NumericRow {
|
||||
rtiny,
|
||||
rsmall,
|
||||
rmedium,
|
||||
rint,
|
||||
rbig,
|
||||
rfloat,
|
||||
rdouble,
|
||||
rutiny,
|
||||
rusmall,
|
||||
rumedium,
|
||||
ruint,
|
||||
rubig,
|
||||
rtinyint1,
|
||||
rbool,
|
||||
};
|
||||
|
||||
response_lines.push(format!("row: {:#?}", row));
|
||||
}
|
||||
|
||||
let response = format!(
|
||||
"Found {} rows(s) as follows:\n{}\n\n(Column info: {})\n",
|
||||
response_lines.len(),
|
||||
response_lines.join("\n"),
|
||||
column_summary,
|
||||
);
|
||||
|
||||
Ok(http::Response::builder()
|
||||
.status(200)
|
||||
.body(Some(response.into()))?)
|
||||
}
|
||||
|
||||
fn test_character_types(_req: Request) -> Result<Response> {
|
||||
let address = std::env::var(DB_URL_ENV)?;
|
||||
|
||||
let create_table_sql = r#"
|
||||
CREATE TEMPORARY TABLE test_character_types (
|
||||
rvarchar varchar(40) NOT NULL,
|
||||
rtext text NOT NULL,
|
||||
rchar char(10) NOT NULL,
|
||||
rbinary binary(10) NOT NULL,
|
||||
rvarbinary varbinary(10) NOT NULL,
|
||||
rblob BLOB NOT NULL
|
||||
);
|
||||
"#;
|
||||
|
||||
mysql::execute(&address, create_table_sql, &[])
|
||||
.map_err(|e| anyhow!("Error executing MySQL command: {:?}", e))?;
|
||||
|
||||
let insert_sql = r#"
|
||||
INSERT INTO test_character_types
|
||||
(rvarchar, rtext, rchar, rbinary, rvarbinary, rblob)
|
||||
VALUES
|
||||
('rvarchar', 'rtext', 'rchar', 'a', 'a', 'a');
|
||||
"#;
|
||||
|
||||
mysql::execute(&address, insert_sql, &[])?;
|
||||
|
||||
let sql = r#"
|
||||
SELECT
|
||||
rvarchar, rtext, rchar, rbinary, rvarbinary, rblob
|
||||
FROM test_character_types;
|
||||
"#;
|
||||
|
||||
let rowset = mysql::query(&address, sql, &[])?;
|
||||
|
||||
let column_summary = rowset
|
||||
.columns
|
||||
.iter()
|
||||
.map(format_col)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
let mut response_lines = vec![];
|
||||
|
||||
for row in rowset.rows {
|
||||
let rvarchar = String::decode(&row[0])?;
|
||||
let rtext = String::decode(&row[1])?;
|
||||
let rchar = String::decode(&row[2])?;
|
||||
let rbinary = Vec::<u8>::decode(&row[3])?;
|
||||
let rvarbinary = Vec::<u8>::decode(&row[4])?;
|
||||
let rblob = Vec::<u8>::decode(&row[5])?;
|
||||
|
||||
let row = CharacterRow {
|
||||
rvarchar,
|
||||
rtext,
|
||||
rchar,
|
||||
rbinary,
|
||||
rvarbinary,
|
||||
rblob,
|
||||
};
|
||||
|
||||
response_lines.push(format!("row: {:#?}", row));
|
||||
}
|
||||
|
||||
let response = format!(
|
||||
"Found {} rows(s) as follows:\n{}\n\n(Column info: {})\n",
|
||||
response_lines.len(),
|
||||
response_lines.join("\n"),
|
||||
column_summary,
|
||||
);
|
||||
|
||||
Ok(http::Response::builder()
|
||||
.status(200)
|
||||
.body(Some(response.into()))?)
|
||||
}
|
||||
|
||||
fn format_col(column: &mysql::Column) -> String {
|
||||
format!("{}: {:?}", column.name, column.data_type)
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
[build]
|
||||
target = "wasm32-wasi"
|
|
@ -1,11 +1,11 @@
|
|||
mod testcases;
|
||||
#[cfg(feature = "new-e2e-tests")]
|
||||
#[cfg(feature = "e2e-tests")]
|
||||
use {e2e_testing::controller::Controller, e2e_testing::spin_controller::SpinUp};
|
||||
|
||||
#[cfg(feature = "new-e2e-tests")]
|
||||
#[cfg(feature = "e2e-tests")]
|
||||
const CONTROLLER: &dyn Controller = &SpinUp {};
|
||||
|
||||
#[cfg(feature = "new-e2e-tests")]
|
||||
#[cfg(feature = "e2e-tests")]
|
||||
mod spinup_tests {
|
||||
use super::testcases;
|
||||
use super::CONTROLLER;
|
||||
|
@ -71,6 +71,11 @@ mod spinup_tests {
|
|||
testcases::all::http_rust_outbound_mysql_works(CONTROLLER).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn http_rust_outbound_pg_works() {
|
||||
testcases::all::http_rust_outbound_pg_works(CONTROLLER).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redis_go_works() {
|
||||
testcases::all::redis_go_works(CONTROLLER).await
|
||||
|
|
|
@ -5,7 +5,7 @@ trigger = { type = "http", base = "/" }
|
|||
version = "0.1.0"
|
||||
|
||||
[[component]]
|
||||
environment = { DB_URL = "host=localhost user=postgres dbname=spin_dev" }
|
||||
environment = { DB_URL = "host=postgres user=postgres password=postgres dbname=spin_dev" }
|
||||
id = "outbound-pg"
|
||||
source = "target/wasm32-wasi/release/http_rust_outbound_pg.wasm"
|
||||
[component.trigger]
|
|
@ -1,4 +1,4 @@
|
|||
#[cfg(feature = "new-e2e-tests")]
|
||||
#[cfg(feature = "e2e-tests")]
|
||||
pub mod all {
|
||||
use anyhow::Result;
|
||||
use e2e_testing::asserts::assert_http_response;
|
||||
|
@ -578,4 +578,61 @@ pub mod all {
|
|||
|
||||
tc.run(controller).await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn http_rust_outbound_pg_works(controller: &dyn Controller) {
|
||||
async fn checks(
|
||||
metadata: AppMetadata,
|
||||
_: Option<BufReader<ChildStdout>>,
|
||||
_: Option<BufReader<ChildStderr>>,
|
||||
) -> Result<()> {
|
||||
assert_http_response(
|
||||
get_url(metadata.base.as_str(), "/test_numeric_types").as_str(),
|
||||
200,
|
||||
&[],
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_http_response(
|
||||
get_url(metadata.base.as_str(), "/test_character_types").as_str(),
|
||||
200,
|
||||
&[],
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_http_response(
|
||||
get_url(metadata.base.as_str(), "/test_general_types").as_str(),
|
||||
200,
|
||||
&[],
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_http_response(
|
||||
get_url(metadata.base.as_str(), "/pg_backend_pid").as_str(),
|
||||
200,
|
||||
&[],
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let tc = TestCaseBuilder::default()
|
||||
.name("http-rust-outbound-pg".to_string())
|
||||
.appname(Some("http-rust-outbound-pg".to_string()))
|
||||
.assertions(
|
||||
|metadata: AppMetadata,
|
||||
stdout_stream: Option<BufReader<ChildStdout>>,
|
||||
stderr_stream: Option<BufReader<ChildStderr>>| {
|
||||
Box::pin(checks(metadata, stdout_stream, stderr_stream))
|
||||
},
|
||||
)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
tc.run(controller).await.unwrap()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue