[ci] Fixes for cli_integration. Debugging for websocket tests (#2453)

This commit is contained in:
Salvador Girones Gil 2023-08-18 09:16:13 +02:00 committed by GitHub
parent b2b51b54b1
commit 22f4c44989
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 178 additions and 101 deletions

View file

@ -172,6 +172,16 @@ jobs:
command: make
args: ci-cli-integration
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true
http-server:
name: HTTP integration tests
runs-on: ubuntu-latest
@ -326,6 +336,15 @@ jobs:
command: make
args: ci-api-integration-ws
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true
http-engine:
name: HTTP engine
runs-on: ubuntu-latest
@ -363,42 +382,60 @@ jobs:
command: make
args: ci-api-integration-http
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true
any-engine:
name: Any engine
runs-on: ubuntu-latest
steps:
name: Any engine
runs-on: ubuntu-latest
steps:
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
- name: Checkout sources
uses: actions/checkout@v3
- name: Checkout sources
uses: actions/checkout@v3
- name: Setup cache
uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Setup cache
uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Install dependencies
run: |
sudo apt-get -y update
- name: Install dependencies
run: |
sudo apt-get -y update
- name: Setup FoundationDB
uses: foundationdb-rs/foundationdb-actions-install@v2.0.0
with:
version: "7.1.30"
- name: Setup FoundationDB
uses: foundationdb-rs/foundationdb-actions-install@v2.0.0
with:
version: "7.1.30"
- name: Install cargo-make
uses: actions-rs/cargo@v1
with:
command: install
args: --debug cargo-make
- name: Install cargo-make
uses: actions-rs/cargo@v1
with:
command: install
args: --debug cargo-make
- name: Test any engine
uses: actions-rs/cargo@v1
with:
command: make
args: ci-api-integration-any
- name: Test any engine
uses: actions-rs/cargo@v1
with:
command: make
args: ci-api-integration-any
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true
mem-engine:
name: Memory engine
@ -549,6 +586,15 @@ jobs:
command: make
args: ci-api-integration-tikv
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true
fdb-engine:
name: FoundationDB engine
runs-on: ubuntu-latest
@ -581,3 +627,12 @@ jobs:
with:
command: make
args: ci-api-integration-fdb
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true

View file

@ -57,6 +57,15 @@ jobs:
command: make
args: ci-workspace-coverage
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true
- name: Upload coverage report
uses: actions/upload-artifact@v3
with:

View file

@ -57,6 +57,15 @@ jobs:
command: make
args: ci-workspace-coverage-complete
- name: Debug info
if: always()
run: |
set -x
free -m
df -h
ps auxf
cat /tmp/surrealdb.log || true
- name: Upload coverage report
uses: actions/upload-artifact@v3
with:

View file

@ -143,7 +143,7 @@ run_task = { name = ["start-tikv", "ci-api-integration-tikv-tests", "stop-tikv"]
category = "CI - SERVICES"
dependencies = ["build-surrealdb"]
script = """
#!/bin/bash
#!/bin/bash -ex
target/debug/surreal start ${_START_SURREALDB_PATH} &>/tmp/surrealdb.log &
@ -163,19 +163,21 @@ script = """
[tasks.stop-surrealdb]
category = "CI - SERVICES"
script = "kill $(cat /tmp/surreal.pid) || true"
script = """
kill $(cat /tmp/surreal.pid) || true
sleep 5
kill -9 $(cat /tmp/surreal.pid) || true
"""
[tasks.start-tikv]
category = "CI - SERVICES"
script = """
#!/bin/bash
#!/bin/bash -ex
${HOME}/.tiup/bin/tiup install pd tikv playground
${HOME}/.tiup/bin/tiup playground --mode tikv-slim --kv 3 --without-monitor &>/tmp/tiup.log &
${HOME}/.tiup/bin/tiup clean --all
echo $! > /tmp/tiup.pid
set +e

View file

@ -32,11 +32,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1690179764,
"narHash": "sha256-Sgszrn/3KnemTBYHnJBwdCcY/u6Gc8FMGHAB+VpPH6I=",
"lastModified": 1692253212,
"narHash": "sha256-vLwYUD/TjjVx9dkuQMIL0la+VpuqwFohzGFn+3AGq+k=",
"owner": "nix-community",
"repo": "fenix",
"rev": "dce10f32abcc7740e5090e021b2c83a6b2ddb614",
"rev": "5d85dc369f8ee47f1cef83999d0de4bb18def5d2",
"type": "github"
},
"original": {
@ -113,11 +113,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1690176526,
"narHash": "sha256-SHdHTRu1RMLhIkTlFMSSyUJYsPNWw50Ky9W6znxGN9A=",
"lastModified": 1692232013,
"narHash": "sha256-a5hct9pN+RSxLclPBsWCg9zOCG9c0Uf1cq3XlntQpDQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a58eb89c7fcb703554aa53b4d25b50bd62e16786",
"rev": "edf586f399ddb6aef26edc2df3aa843e97a2ddc1",
"type": "github"
},
"original": {
@ -139,11 +139,11 @@
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1690057540,
"narHash": "sha256-MKGhZsFTpJH3Sq+9dGFGqOje3A6PD6fKGO92tM23zuY=",
"lastModified": 1692173342,
"narHash": "sha256-0JgH5lhg0AaUYeEqVAfWnVJPwOFu0dbvDVGIb0F9kUA=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "99718d0c8bc5aadd993acdcabc1778fc7b5cc572",
"rev": "e69b96bd40a47d7919894e3220f9d43698888a84",
"type": "github"
},
"original": {

View file

@ -175,30 +175,20 @@ async fn all_commands() {
#[test(tokio::test)]
async fn start_tls() {
// Capute the server's stdout/stderr
temp_env::async_with_vars(
[
("SURREAL_TEST_SERVER_STDOUT", Some("piped")),
("SURREAL_TEST_SERVER_STDERR", Some("piped")),
],
async {
let (_, server) = common::start_server(StartServerArguments {
auth: false,
tls: true,
wait_is_ready: false,
tick_interval: ONE_SEC,
})
.await
.unwrap();
let (_, server) = common::start_server(StartServerArguments {
auth: false,
tls: true,
wait_is_ready: false,
tick_interval: ONE_SEC,
})
.await
.unwrap();
std::thread::sleep(std::time::Duration::from_millis(2000));
let output = server.kill().output().err().unwrap();
std::thread::sleep(std::time::Duration::from_millis(2000));
let output = server.kill().output().err().unwrap();
// Test the crt/key args but the keys are self signed so don't actually connect.
assert!(output.contains("Started web server"), "couldn't start web server: {output}");
},
)
.await;
// Test the crt/key args but the keys are self signed so don't actually connect.
assert!(output.contains("Started web server"), "couldn't start web server: {output}");
}
#[test(tokio::test)]

View file

@ -24,6 +24,8 @@ pub const PASS: &str = "root";
/// Child is a (maybe running) CLI process. It can be killed by dropping it
pub struct Child {
inner: Option<std::process::Child>,
stdout_path: String,
stderr_path: String,
}
impl Child {
@ -43,12 +45,19 @@ impl Child {
/// Read the child's stdout concatenated with its stderr. Returns Ok if the child
/// returns successfully, Err otherwise.
pub fn output(mut self) -> Result<String, String> {
let output = self.inner.take().unwrap().wait_with_output().unwrap();
let status = self.inner.take().unwrap().wait().unwrap();
let mut buf = String::from_utf8(output.stdout).unwrap();
buf.push_str(&String::from_utf8(output.stderr).unwrap());
let mut buf =
std::fs::read_to_string(&self.stdout_path).expect("Failed to read the stdout file");
buf.push_str(
&std::fs::read_to_string(&self.stderr_path).expect("Failed to read the stderr file"),
);
if output.status.success() {
// Cleanup files after reading them
std::fs::remove_file(self.stdout_path.as_str()).unwrap();
std::fs::remove_file(self.stderr_path.as_str()).unwrap();
if status.success() {
Ok(buf)
} else {
Err(buf)
@ -64,12 +73,7 @@ impl Drop for Child {
}
}
pub fn run_internal<P: AsRef<Path>>(
args: &str,
current_dir: Option<P>,
stdout: Stdio,
stderr: Stdio,
) -> Child {
pub fn run_internal<P: AsRef<Path>>(args: &str, current_dir: Option<P>) -> Child {
let mut path = std::env::current_exe().unwrap();
assert!(path.pop());
if path.ends_with("deps") {
@ -83,24 +87,35 @@ pub fn run_internal<P: AsRef<Path>>(
if let Some(dir) = current_dir {
cmd.current_dir(&dir);
}
// Use local files instead of pipes to avoid deadlocks. See https://github.com/rust-lang/rust/issues/45572
let stdout_path = tmp_file(format!("server-stdout-{}.log", rand::random::<u32>()).as_str());
let stderr_path = tmp_file(format!("server-stderr-{}.log", rand::random::<u32>()).as_str());
debug!("Logging server output to: ({}, {})", stdout_path, stderr_path);
let stdout = Stdio::from(File::create(&stdout_path).unwrap());
let stderr = Stdio::from(File::create(&stderr_path).unwrap());
cmd.env_clear();
cmd.stdin(Stdio::piped());
cmd.stdout(stdout);
cmd.stderr(stderr);
cmd.args(args.split_ascii_whitespace());
Child {
inner: Some(cmd.spawn().unwrap()),
stdout_path,
stderr_path,
}
}
/// Run the CLI with the given args
pub fn run(args: &str) -> Child {
run_internal::<String>(args, None, Stdio::piped(), Stdio::piped())
run_internal::<String>(args, None)
}
/// Run the CLI with the given args inside a temporary directory
pub fn run_in_dir<P: AsRef<Path>>(args: &str, current_dir: P) -> Child {
run_internal(args, Some(current_dir), Stdio::piped(), Stdio::piped())
run_internal(args, Some(current_dir))
}
pub fn tmp_file(name: &str) -> String {
@ -108,19 +123,6 @@ pub fn tmp_file(name: &str) -> String {
path.to_string_lossy().into_owned()
}
fn parse_server_stdio_from_var(var: &str) -> Result<Stdio, Box<dyn Error>> {
match env::var(var).as_deref() {
Ok("inherit") => Ok(Stdio::inherit()),
Ok("null") => Ok(Stdio::null()),
Ok("piped") => Ok(Stdio::piped()),
Ok(val) if val.starts_with("file://") => {
Ok(Stdio::from(File::create(val.trim_start_matches("file://"))?))
}
Ok(val) => Err(format!("Unsupported stdio value: {val:?}").into()),
_ => Ok(Stdio::null()),
}
}
pub struct StartServerArguments {
pub auth: bool,
pub tls: bool,
@ -191,9 +193,7 @@ pub async fn start_server(
info!("starting server with args: {start_args}");
// Configure where the logs go when running the test
let stdout = parse_server_stdio_from_var("SURREAL_TEST_SERVER_STDOUT")?;
let stderr = parse_server_stdio_from_var("SURREAL_TEST_SERVER_STDERR")?;
let server = run_internal::<String>(&start_args, None, stdout, stderr);
let server = run_internal::<String>(&start_args, None);
if !wait_is_ready {
return Ok((addr, server));
@ -328,9 +328,16 @@ pub async fn ws_signin(
Some(obj) if obj.keys().all(|k| ["id", "error"].contains(&k.as_str())) => {
Err(format!("unexpected error from query request: {:?}", obj.get("error")).into())
}
Some(obj) if obj.keys().all(|k| ["id", "result"].contains(&k.as_str())) => {
Ok(obj.get("result").unwrap().as_str().unwrap_or_default().to_owned())
}
Some(obj) if obj.keys().all(|k| ["id", "result"].contains(&k.as_str())) => Ok(obj
.get("result")
.ok_or(TestError::AssertionError {
message: format!("expected a result from the received object, got this instead: {:?}", obj),
})?
.as_str()
.ok_or(TestError::AssertionError {
message: format!("expected the result object to be a string for the received ws message, got this instead: {:?}", obj.get("result")).to_string(),
})?
.to_owned()),
_ => {
error!("{:?}", msg.as_object().unwrap().keys().collect::<Vec<_>>());
Err(format!("unexpected response: {:?}", msg).into())
@ -358,12 +365,11 @@ pub async fn ws_query(
Some(obj) if obj.keys().all(|k| ["id", "result"].contains(&k.as_str())) => Ok(obj
.get("result")
.ok_or(TestError::AssertionError {
message: "expected a result from the received object".to_string(),
message: format!("expected a result from the received object, got this instead: {:?}", obj),
})?
.as_array()
.ok_or(TestError::AssertionError {
message: "expected the result object to be an array for the received ws message"
.to_string(),
message: format!("expected the result object to be an array for the received ws message, got this instead: {:?}", obj.get("result")).to_string(),
})?
.to_owned()),
_ => {
@ -393,9 +399,15 @@ pub async fn ws_use(
Some(obj) if obj.keys().all(|k| ["id", "error"].contains(&k.as_str())) => {
Err(format!("unexpected error from query request: {:?}", obj.get("error")).into())
}
Some(obj) if obj.keys().all(|k| ["id", "result"].contains(&k.as_str())) => {
Ok(obj.get("result").unwrap().to_owned())
}
Some(obj) if obj.keys().all(|k| ["id", "result"].contains(&k.as_str())) => Ok(obj
.get("result")
.ok_or(TestError::AssertionError {
message: format!(
"expected a result from the received object, got this instead: {:?}",
obj
),
})?
.to_owned()),
_ => {
error!("{:?}", msg.as_object().unwrap().keys().collect::<Vec<_>>());
Err(format!("unexpected response: {:?}", msg).into())