Skip to content

Commit

Permalink
the feature run wasm directly (#46)
Browse files Browse the repository at this point in the history
* the feature run wasm directly

* add the test for CliConfig

* add the test for main

* add the test for main

* add the test for main

* let the config log level to warn

* the configure setting with the command line

* add uni test for config

* recover
  • Loading branch information
Joinhack authored Apr 12, 2023
1 parent 7f47744 commit 360a0b2
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 8 deletions.
1 change: 1 addition & 0 deletions blockless-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ tokio = {version = "1", features = ["rt", "net", "time"]}
log = "0.4.17"
rust-car = {workspace = true}
md5 = {workspace = true}
clap = "4.2.1"

[dependencies.env_logger]
version = "0.8"
125 changes: 125 additions & 0 deletions blockless-cli/src/cli_clap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#![allow(unused)]
use blockless::BlocklessConfig;
use clap::{Arg, ArgMatches, Command};

pub(crate) fn cli_command() -> Command {
Command::new("blockless_cli")
.arg(
Arg::new("input")
.help("the input file is wasm file, configure file, or car file")
.required(true)
)
.arg(
Arg::new("debug_info")
.long("debug_info")
.help("the debug info for the runtime.")
.required(false),
)
.arg(
Arg::new("fs_root_path")
.long("fs_root_path")
.help("the root directory for the runtime.")
.required(false),
)
.arg(
Arg::new("runtime_logger")
.long("runtime_logger")
.help("the logger file for the runtime.")
.required(false),
)
.arg(
Arg::new("limited_memory")
.long("limited_memory")
.help("the limited memory for the runtime, default is infine.")
.required(false),
)
.arg(
Arg::new("run_time")
.long("run_time")
.help("the run time for the runtime, default is infine.")
.required(false),
)
.arg(
Arg::new("entry")
.long("entry")
.help("the entry for wasm, default is _start")
.required(false),
)
.arg(
Arg::new("limited_fuel")
.long("limited_fuel")
.help("the limited fuel for runtime, default is infine")
.required(false),
)
.allow_missing_positional(true)
}

#[rustfmt::skip]
pub(crate) fn apply_config(cfg: &mut BlocklessConfig, matches: &ArgMatches) {
matches.get_one::<bool>("debug_info").map(|d| cfg.debug_info(*d));
matches.get_one::<String>("fs_root_path").map(|f| cfg.fs_root_path(Some(f.clone())));
matches.get_one::<String>("runtime_logger").map(|f| cfg.runtime_logger(Some(f.clone())));
matches.get_one::<String>("entry").map(|f| cfg.entry(f.clone()));
matches.get_one::<u64>("limited_memory").map(|f| cfg.limited_memory(Some(*f)));
matches.get_one::<u64>("run_time").map(|f| cfg.set_run_time(Some(*f)));
matches.get_one::<u64>("limited_fuel").map(|f| cfg.limited_fuel(Some(*f)));
}

#[cfg(test)]
mod test {

#[allow(unused)]
use super::*;

#[test]
fn test_cli_command_input() {
let cli_cmd = cli_command();
let command_line = r#"blockless_cli test.wasm"#;
let command_line = command_line
.split(" ")
.map(str::to_string)
.collect::<Vec<String>>();
let matches = cli_cmd.try_get_matches_from(command_line).unwrap();
let input = matches.get_one::<String>("input");
let pat = match input {
Some(p) => p,
None => unreachable!("can't reach here!"),
};
assert_eq!(pat, &"test.wasm");
}

#[test]
fn test_cli_command_runtime_log() {
let cli_cmd = cli_command();
let command_line = r#"blockless_cli test.wasm --runtime_logger runtime.log"#;
let command_line = command_line
.split(" ")
.map(str::to_string)
.collect::<Vec<String>>();
let matches = cli_cmd.try_get_matches_from(command_line).unwrap();
let input = matches.get_one::<String>("runtime_logger");
let pat = match input {
Some(p) => p,
None => unreachable!("can't reach here!"),
};
assert_eq!(pat, &"runtime.log");
}

#[test]
fn test_cli_command_fs_root_path() {
let cli_cmd = cli_command();
let command_line = r#"blockless_cli test.wasm --fs_root_path /"#;
let command_line = command_line
.split(" ")
.map(str::to_string)
.collect::<Vec<String>>();
let matches = cli_cmd.try_get_matches_from(command_line).unwrap();
let input = matches.get_one::<String>("fs_root_path");
let pat = match input {
Some(p) => p,
None => unreachable!("can't reach here!"),
};
assert_eq!(pat, &"/");
}

}
58 changes: 58 additions & 0 deletions blockless-cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use blockless::{self, LoggerLevel, BlocklessModule, ModuleType};
use blockless::{BlocklessConfig, DriverConfig, MultiAddr, Permission};
use json::{self, JsonValue};
use std::env::VarError;
use std::ffi::OsStr;
use std::fs;
use std::os::unix::prelude::OsStrExt;
use std::path::{PathBuf, Path};

pub(crate) struct CliConfig(pub(crate) BlocklessConfig);
Expand All @@ -15,6 +17,33 @@ struct EnvVar {

impl CliConfig {

fn defaut_logger_file(filen: &OsStr) -> Option<String> {
let filen = filen.as_bytes();
let p = match filen.iter().position(|b| *b == b'.') {
Some(p) => p,
None => return Some("runtime".to_string()),
};
OsStr::from_bytes(&filen[..p])
.to_os_string()
.to_str()
.map(String::from)
}

/// config the wasm file as entry file
/// current directory as the root path
pub fn new_with_wasm(wasm_file: impl AsRef<Path>) -> CliConfig {
let file_path = wasm_file.as_ref();
let file_name = file_path.file_name().unwrap();
let log_file = Self::defaut_logger_file(file_name);
let mut bconf = BlocklessConfig::new(file_path.to_str().unwrap());
bconf.fs_root_path(Some(".".to_string()));
bconf.runtime_logger_level(LoggerLevel::WARN);
log_file.as_ref().map(|log_file| {
bconf.runtime_logger(Some(format!("{log_file}.log")));
});
CliConfig(bconf)
}

fn permissions(permission_json: &JsonValue) -> Vec<Permission> {
match *permission_json {
JsonValue::Array(ref perms) => perms
Expand Down Expand Up @@ -184,10 +213,39 @@ impl CliConfig {
#[cfg(test)]
mod test {
#![allow(unused)]
use std::ffi::OsString;

use blockless::BlocklessConfigVersion;

use super::*;

#[test]
fn test_defaut_logger_file() {
let filen: OsString = "test.wasm".into();
let filen = CliConfig::defaut_logger_file(&filen);
let filen = filen.unwrap();
assert_eq!(filen, "test".to_string());

let filen: OsString = "test".into();
let filen = CliConfig::defaut_logger_file(&filen);
let filen = filen.unwrap();
assert_eq!(filen, "runtime".to_string());
}

#[test]
fn test_new_with_wasm() {
let cliconf = CliConfig::new_with_wasm("test.wasm");
let current = Some(".");
let root_path = cliconf.0.fs_root_path_ref();
assert_eq!(root_path, current);
let config_logger_ref = cliconf.0.runtime_logger_ref();
let logger_ref = Some("./test.log".into());
assert_eq!(logger_ref, config_logger_ref);

let logger_level = cliconf.0.runtime_logger_level_ref();
assert!(matches!(&LoggerLevel::WARN, logger_level));
}

#[test]
fn test_load_config() {
let data = r#"{
Expand Down
37 changes: 30 additions & 7 deletions blockless-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
mod cli_clap;
mod config;
use blockless::{
blockless_run,
LoggerLevel
};
#[allow(unused_imports)]
use cli_clap::apply_config;
use config::CliConfig;
use anyhow::Result;
use std::{
env,
io::{self, Read},
fs::File,
path::PathBuf,
time::Duration,
process::ExitCode
process::ExitCode, env
};
use env_logger::Target;
use tokio::runtime::Builder;
Expand Down Expand Up @@ -117,19 +119,30 @@ fn check_module_sum(cfg: &CliConfig) -> Option<i32> {
None
}

fn load_cli_config(conf_path: &str) -> Result<CliConfig> {
let ext = Path::new(conf_path).extension();
fn load_wasm_directly(wasmfile: &str) -> Result<CliConfig> {
Ok(CliConfig::new_with_wasm(wasmfile))
}

/// the cli support 3 type file,
/// 1. the car file format, all files archive into the car file.
/// 2. the wasm or wasi file format, will run wasm directly.
/// 3. the the config file, format, all files is define in the config file.
fn load_cli_config(file_path: &str) -> Result<CliConfig> {
let ext = Path::new(file_path).extension();
let cfg = ext.and_then(|ext| ext.to_str().map(str::to_ascii_lowercase));
let cli_config = match cfg {
Some(f) if f == "car" => {
Some(ext) if ext == "car" => {
let file = fs::OpenOptions::new()
.read(true)
.open(conf_path)?;
.open(file_path)?;
Some(load_extract_from_car(file))
},
Some(ext) if ext == "wasm" || ext == "wasi" => {
Some(load_wasm_directly(file_path))
},
_ => None,
};
cli_config.unwrap_or_else(|| CliConfig::from_file(conf_path))
cli_config.unwrap_or_else(|| CliConfig::from_file(file_path))
}

fn main() -> ExitCode {
Expand Down Expand Up @@ -191,6 +204,16 @@ mod test {
};
use super::*;

#[test]
fn test_load_cli_wasm_config() {
let wasm_conf = load_cli_config("test.wasm");
let wasm_conf = wasm_conf.unwrap();
let entry_ref = wasm_conf.0.entry_ref();
assert_eq!(entry_ref, "test.wasm");
let root_path_ref = wasm_conf.0.fs_root_path_ref();
assert_eq!(root_path_ref, Some("."));
}

#[test]
fn test_load_from_car() {
let mut buf = Vec::new();
Expand Down
11 changes: 10 additions & 1 deletion crates/wasi-common/src/blockless/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ impl BlocklessConfig {
self.veriosn
}

#[inline(always)]
pub fn entry(&mut self, entry: String) {
self.entry = entry;
}

#[inline(always)]
pub fn set_version(&mut self, version: BlocklessConfigVersion) {
self.veriosn = version;
Expand Down Expand Up @@ -258,7 +263,7 @@ impl BlocklessConfig {
entry: String::from(entry),
permisions: Default::default(),
group_permisions: HashMap::new(),
runtime_logger_level: LoggerLevel::INFO,
runtime_logger_level: LoggerLevel::WARN,
veriosn: BlocklessConfigVersion::Version0,
}
}
Expand Down Expand Up @@ -396,6 +401,10 @@ mod test {
config.runtime_logger(test);
let result = PathBuf::new().join("/root").join("test.log");
assert_eq!(config.runtime_logger_ref().unwrap(), result);

assert_eq!(config.entry_ref(), "test");
config.entry("_start".into());
assert_eq!(config.entry_ref(), "_start");
}

#[test]
Expand Down

0 comments on commit 360a0b2

Please sign in to comment.