Skip to content

Commit

Permalink
Merge pull request #175 from NethermindEth/feature/scarb-test
Browse files Browse the repository at this point in the history
Add Scarb Test
  • Loading branch information
stranger80 authored Oct 24, 2023
2 parents 8b6ca3b + e1564d2 commit a2bc627
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 4 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/rust-linting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
on:
pull_request:
branches:
- develop

jobs:
rustfmt:
name: Rustfmt
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
- run: rustup component add rustfmt --toolchain nightly
- run: cd api && cargo +nightly fmt --all -- --check

clippy:
name: Clippy
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
- run: rustup component add clippy --toolchain nightly
- run: cd api && cargo +nightly clippy --all -- -D warnings
1 change: 0 additions & 1 deletion api/src/handlers/cairo_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub async fn cairo_version_async(
#[instrument]
#[get("/cairo_version_result/<process_id>")]
pub async fn get_cairo_version_result(process_id: String, engine: &State<WorkerEngine>) -> String {
info!("/cairo_version_result/{:?}", process_id);
fetch_process_result(process_id, engine, |result| match result {
ApiCommandResult::CairoVersion(version) => version.to_string(),
_ => String::from("Result not available"),
Expand Down
1 change: 1 addition & 0 deletions api/src/handlers/compile_casm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::process::{Command, Stdio};
use tracing::info;
use tracing::instrument;

#[instrument]
#[get("/compile-to-casm/<version>/<remix_file_path..>")]
pub async fn compile_to_casm(
version: String,
Expand Down
6 changes: 6 additions & 0 deletions api/src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ pub mod compile_sierra;
pub mod process;
pub mod save_code;
pub mod scarb_compile;
pub mod scarb_test;
pub mod types;

use crate::handlers::cairo_version::do_cairo_version;
use crate::handlers::compile_casm::do_compile_to_casm;
use crate::handlers::compile_sierra::do_compile_to_sierra;
use crate::handlers::scarb_compile::do_scarb_compile;
use crate::handlers::scarb_test::do_scarb_test;
use crate::handlers::types::{ApiCommand, ApiCommandResult, FileContentMap};
use crate::types::{ApiError, Result};
use rocket::serde::json::Json;
Expand Down Expand Up @@ -61,6 +63,10 @@ pub async fn dispatch_command(command: ApiCommand) -> Result<ApiCommandResult> {
Err(e) => Err(e),
},
ApiCommand::Shutdown => Ok(ApiCommandResult::Shutdown),
ApiCommand::ScarbTest { remix_file_path } => match do_scarb_test(remix_file_path).await {
Ok(result) => Ok(ApiCommandResult::ScarbTest(result.into_inner())),
Err(e) => Err(e),
},
}
}

Expand Down
4 changes: 2 additions & 2 deletions api/src/handlers/process.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::handlers::types::{ApiCommand, ApiCommandResult};
use crate::worker::{ProcessState, WorkerEngine};
use rocket::State;
use tracing::{info, instrument};
use tracing::instrument;
use uuid::Uuid;

#[instrument]
Expand All @@ -22,7 +22,7 @@ pub async fn get_process_status(process_id: String, engine: &State<WorkerEngine>
)
} else {
// TODO can we return HTTP status code here?
format!("Process id not found")
format!("Process with id={} not found", process_id)
}
}
Err(e) => {
Expand Down
2 changes: 1 addition & 1 deletion api/src/handlers/scarb_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rocket::serde::json::Json;
use rocket::State;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use tracing::{info, instrument};
use tracing::instrument;

#[instrument]
#[get("/compile-scarb/<remix_file_path..>")]
Expand Down
90 changes: 90 additions & 0 deletions api/src/handlers/scarb_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use crate::handlers::process::{do_process_command, fetch_process_result};
use crate::handlers::types::{ApiCommand, ApiCommandResult, ScarbTestResponse};
use crate::rate_limiter::RateLimited;
use crate::types::ApiError;
use crate::types::Result;
use crate::utils::lib::get_file_path;
use crate::worker::WorkerEngine;
use rocket::serde::json;
use rocket::serde::json::Json;
use rocket::State;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use tracing::instrument;

#[instrument]
#[get("/scarb-test-async/<remix_file_path..>")]
pub async fn scarb_test_async(
remix_file_path: PathBuf,
engine: &State<WorkerEngine>,
_rate_limited: RateLimited,
) -> String {
info!("/scarb-test-async/{:?}", remix_file_path);
do_process_command(ApiCommand::ScarbTest { remix_file_path }, engine)
}

#[instrument]
#[get("/scarb-test-result/<process_id>")]
pub async fn get_scarb_test_result(process_id: String, engine: &State<WorkerEngine>) -> String {
info!("/scarb-test-result/{:?}", process_id);
fetch_process_result(process_id, engine, |result| match result {
ApiCommandResult::ScarbTest(scarb_result) => json::to_string(&scarb_result)
.unwrap_or_else(|e| format!("Failed to fetch result: {:?}", e)),
_ => String::from("Result not available"),
})
}

/// Run Scarb to test a project
///
pub async fn do_scarb_test(remix_file_path: PathBuf) -> Result<Json<ScarbTestResponse>> {
let remix_file_path = remix_file_path
.to_str()
.ok_or(ApiError::FailedToParseString)?
.to_string();

let file_path = get_file_path(&remix_file_path);

let mut compile = Command::new("scarb");
compile.current_dir(&file_path);

let result = compile
.arg("test")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.map_err(ApiError::FailedToExecuteCommand)?;

debug!("LOG: ran command:{:?}", compile);

let output = result
.wait_with_output()
.map_err(ApiError::FailedToReadOutput)?;

let message = String::from_utf8(output.stdout)
.map_err(ApiError::UTF8Error)?
.replace(
&file_path
.to_str()
.ok_or(ApiError::FailedToParseString)?
.to_string(),
&remix_file_path,
)
+ &String::from_utf8(output.stderr)
.map_err(ApiError::UTF8Error)?
.replace(
&file_path
.to_str()
.ok_or(ApiError::FailedToParseString)?
.to_string(),
&remix_file_path,
);

let status = match output.status.code() {
Some(0) => "Success",
Some(_) => "SierraCompilationFailed",
None => "UnknownError",
}
.to_string();

Ok(Json(ScarbTestResponse { message, status }))
}
10 changes: 10 additions & 0 deletions api/src/handlers/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ pub struct ScarbCompileResponse {
pub file_content_map_array: Vec<FileContentMap>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ScarbTestResponse {
pub status: String,
pub message: String,
}

#[derive(Debug)]
pub enum ApiCommand {
CairoVersion,
Expand All @@ -37,6 +43,9 @@ pub enum ApiCommand {
ScarbCompile {
remix_file_path: PathBuf,
},
ScarbTest {
remix_file_path: PathBuf,
},
#[allow(dead_code)]
Shutdown,
}
Expand All @@ -47,6 +56,7 @@ pub enum ApiCommandResult {
CasmCompile(CompileResponse),
SierraCompile(CompileResponse),
ScarbCompile(ScarbCompileResponse),
ScarbTest(ScarbTestResponse),
#[allow(dead_code)]
Shutdown,
}
3 changes: 3 additions & 0 deletions api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use handlers::compile_sierra::{
use handlers::process::get_process_status;
use handlers::save_code::save_code;
use handlers::scarb_compile::{get_scarb_compile_result, scarb_compile, scarb_compile_async};
use handlers::scarb_test::{get_scarb_test_result, scarb_test_async};
use handlers::{health, who_is_this};
use tracing::info;

Expand Down Expand Up @@ -75,6 +76,8 @@ async fn rocket() -> _ {
get_process_status,
health,
who_is_this,
get_scarb_test_result,
scarb_test_async,
],
)
}

0 comments on commit a2bc627

Please sign in to comment.