diff --git a/.bazelrc b/.bazelrc index 8baa8418..69b0f3c9 100644 --- a/.bazelrc +++ b/.bazelrc @@ -5,6 +5,7 @@ build --tool_java_runtime_version=remotejdk_17 build --@score_baselibs//score/json:base_library=nlohmann build --@score_baselibs//score/mw/log/flags:KRemote_Logging=False +build --@score_baselibs_rust//src/log:safety_level=qm # ToDo: needed for "wrong" implicit dependencies build --@score-baselibs//score/json:base_library=nlohmann diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 09526385..facdd72c 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -38,7 +38,7 @@ jobs: - name: Cargo Clippy run: | - cargo clippy --all-targets --all-features + cargo clippy --all-targets --features logging -- -D warnings - name: Cargo Fmt run: | diff --git a/Cargo.lock b/Cargo.lock index 2b83c72d..5c358e70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,25 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "colored" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +dependencies = [ + "lazy_static", + "windows-sys 0.59.0", +] + +[[package]] +name = "deranged" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +dependencies = [ + "powerfmt", +] + [[package]] name = "errno" version = "0.3.13" @@ -86,25 +105,33 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "overload", - "winapi", + "windows-sys 0.52.0", ] [[package]] -name = "once_cell" -version = "1.21.3" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] -name = "overload" -version = "0.1.1" +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "pico-args" @@ -118,6 +145,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "proc-macro2" version = "1.0.95" @@ -147,6 +180,7 @@ name = "rust_kvs" version = "0.1.0" dependencies = [ "adler32", + "log", "tempfile", "tinyjson", ] @@ -155,8 +189,10 @@ dependencies = [ name = "rust_kvs_tool" version = "0.1.0" dependencies = [ + "log", "pico-args", "rust_kvs", + "simple_logger", "tinyjson", ] @@ -164,9 +200,11 @@ dependencies = [ name = "rust_test_scenarios" version = "0.1.0" dependencies = [ + "log", "rust_kvs", "serde", "serde_json", + "simple_logger", "test_scenarios_rust", "tinyjson", "tracing", @@ -194,18 +232,28 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" dependencies = [ "proc-macro2", "quote", @@ -214,14 +262,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -233,6 +282,18 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "simple_logger" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb" +dependencies = [ + "colored", + "log", + "time", + "windows-sys 0.48.0", +] + [[package]] name = "smallvec" version = "1.15.1" @@ -281,6 +342,39 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinyjson" version = "2.5.1" @@ -342,9 +436,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "nu-ansi-term", "serde", @@ -379,26 +473,22 @@ dependencies = [ ] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-targets 0.48.5", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] [[package]] name = "windows-sys" @@ -418,6 +508,21 @@ dependencies = [ "windows-targets 0.53.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -450,6 +555,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -462,6 +573,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -474,6 +591,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -498,6 +621,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -510,6 +639,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -522,6 +657,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -534,6 +675,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/MODULE.bazel b/MODULE.bazel index a91b7609..4e7bf5dc 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -46,7 +46,7 @@ bazel_dep(name = "score_rust_policies", version = "0.0.2", dev_dependency = True rust = use_extension("@rules_rust//rust:extensions.bzl", "rust", dev_dependency = True) rust.toolchain( edition = "2021", - versions = ["1.85.0"], + versions = ["1.90.0"], ) # bazel cc rules @@ -97,8 +97,37 @@ bazel_dep(name = "score_python_basics", version = "0.3.4") bazel_dep(name = "score_platform", version = "0.4.1") bazel_dep(name = "score_process", version = "1.3.1") -# Module deps -bazel_dep(name = "score_baselibs", version = "0.1.2") +# S-CORE crates +bazel_dep(name = "score_crates", version = "0.0.3") +git_override( + module_name = "score_crates", + # TODO: 'commit' and 'remote' must be updated once required changes are merged. + # https://github.com/eclipse-score/score-crates/pull/16 + commit = "f0bf4bdf98d8a8ad548256ab24dc08f9ba8f04aa", + remote = "https://github.com/qorix-group/score-crates.git", +) + +# S-CORE base libraries and logging library. +bazel_dep(name = "score_baselibs", version = "0.2.0") +git_override( + module_name = "score_baselibs", + commit = "59dba065def85e3c7fb38e08f0d4cb04cc693b2f", + remote = "https://github.com/eclipse-score/baselibs.git", +) + +bazel_dep(name = "score_baselibs_rust", version = "0.1.0") +git_override( + module_name = "score_baselibs_rust", + branch = "arkjedrz_mw-log-main", + remote = "https://github.com/qorix-group/baselibs_rust.git", +) + +bazel_dep(name = "score_logging", version = "0.0.3") +git_override( + module_name = "score_logging", + branch = "arkjedrz_mw-log", + remote = "https://github.com/qorix-group/logging.git", +) ## additional settings / config crate = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate") diff --git a/src/rust/rust_kvs/BUILD b/src/rust/rust_kvs/BUILD index 2b1f3220..2942e3f9 100644 --- a/src/rust/rust_kvs/BUILD +++ b/src/rust/rust_kvs/BUILD @@ -16,15 +16,17 @@ load("@score_persistency_crates//:defs.bzl", "all_crate_deps") rust_library( name = "rust_kvs", srcs = glob(["src/**/*.rs"]), + crate_features = ["score-log"], visibility = ["//visibility:public"], - deps = all_crate_deps( - normal = True, - ), + deps = [ + "@score_baselibs_rust//src/log/mw_log", + ] + all_crate_deps(normal = True), ) rust_test( name = "tests", crate = "rust_kvs", + crate_features = ["score-log"], tags = [ "unit_tests", "ut", diff --git a/src/rust/rust_kvs/Cargo.toml b/src/rust/rust_kvs/Cargo.toml index bf0be609..72f74723 100644 --- a/src/rust/rust_kvs/Cargo.toml +++ b/src/rust/rust_kvs/Cargo.toml @@ -7,6 +7,12 @@ edition.workspace = true [dependencies] adler32.workspace = true tinyjson.workspace = true +log = { version = "0.4.27", optional = true } + +[features] +default = ["logging"] +score-log = [] +logging = ["log"] [dev-dependencies] diff --git a/src/rust/rust_kvs/src/error_code.rs b/src/rust/rust_kvs/src/error_code.rs index ff842527..f5778860 100644 --- a/src/rust/rust_kvs/src/error_code.rs +++ b/src/rust/rust_kvs/src/error_code.rs @@ -11,11 +11,13 @@ extern crate alloc; +use crate::log::error; use alloc::string::FromUtf8Error; use core::array::TryFromSliceError; /// Runtime Error Codes #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "score-log", derive(mw_log::ScoreDebug))] pub enum ErrorCode { /// Error that was not yet mapped UnmappedError, @@ -93,7 +95,7 @@ impl From for ErrorCode { match kind { std::io::ErrorKind::NotFound => ErrorCode::FileNotFound, _ => { - eprintln!("error: unmapped error: {kind}"); + error!("Unmapped IO error: {:?}", kind.to_string()); ErrorCode::UnmappedError } } @@ -102,21 +104,21 @@ impl From for ErrorCode { impl From for ErrorCode { fn from(cause: FromUtf8Error) -> Self { - eprintln!("error: UTF-8 conversion failed: {cause:#?}"); + error!("Conversion from UTF-8 failed: {:#?}", cause); ErrorCode::ConversionFailed } } impl From for ErrorCode { fn from(cause: TryFromSliceError) -> Self { - eprintln!("error: try_into from slice failed: {cause:#?}"); + error!("Conversion from slice failed: {:#?}", cause); ErrorCode::ConversionFailed } } impl From> for ErrorCode { fn from(cause: Vec) -> Self { - eprintln!("error: try_into from u8 vector failed: {cause:#?}"); + error!("Conversion from vector of u8 failed: {:#?}", cause); ErrorCode::ConversionFailed } } diff --git a/src/rust/rust_kvs/src/json_backend.rs b/src/rust/rust_kvs/src/json_backend.rs index 56aa542a..c67ca128 100644 --- a/src/rust/rust_kvs/src/json_backend.rs +++ b/src/rust/rust_kvs/src/json_backend.rs @@ -13,6 +13,7 @@ use crate::error_code::ErrorCode; use crate::kvs_api::{InstanceId, SnapshotId}; use crate::kvs_backend::{KvsBackend, KvsPathResolver}; use crate::kvs_value::{KvsMap, KvsValue}; +use crate::log::{debug, error}; use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; @@ -133,8 +134,8 @@ impl From for JsonValue { /// tinyjson::JsonParseError -> ErrorCode::JsonParseError impl From for ErrorCode { fn from(cause: JsonParseError) -> Self { - eprintln!( - "error: JSON parser error: line = {}, column = {}", + error!( + "JSON parser error: line = {}, column = {}", cause.line(), cause.column() ); @@ -145,7 +146,7 @@ impl From for ErrorCode { /// tinyjson::JsonGenerateError -> ErrorCode::JsonGenerateError impl From for ErrorCode { fn from(cause: JsonGenerateError) -> Self { - eprintln!("error: JSON generator error: msg = {}", cause.message()); + error!("JSON generator error: msg = {}", cause.message()); ErrorCode::JsonGeneratorError } } @@ -171,18 +172,35 @@ impl JsonBackend { impl KvsBackend for JsonBackend { fn load_kvs(kvs_path: &Path, hash_path: &Path) -> Result { + // Check file path extensions. + debug!("Checking KVS file path: {:?}", kvs_path); if !Self::check_extension(kvs_path, "json") { + error!("Invalid KVS file path extension: {:?}", kvs_path); return Err(ErrorCode::KvsFileReadError); } + + debug!("Checking hash file path: {:?}", hash_path); if !Self::check_extension(hash_path, "hash") { + error!("Invalid hash file path extension: {:?}", hash_path); return Err(ErrorCode::KvsHashFileReadError); } // Load KVS file and parse from string to `JsonValue`. - let json_str = fs::read_to_string(kvs_path)?; - let json_value = Self::parse(&json_str)?; + debug!("Loading KVS file: {:?}", kvs_path); + let json_str = fs::read_to_string(kvs_path).inspect_err(|_e| { + error!("Failed to load KVS file: {:?}", kvs_path); + })?; + + debug!("Parsing KVS file: {:?}", kvs_path); + let json_value = Self::parse(&json_str).inspect_err(|_e| { + error!("Failed to parse KVS file: {:?}", kvs_path); + })?; // Perform hash check. + debug!( + "Performing hash check, KVS file: {:?}, hash file: {:?}", + kvs_path, hash_path + ); match fs::read(hash_path) { Ok(hash_bytes) => { let hash_kvs = adler32::RollingAdler32::from_buffer(json_str.as_bytes()).hash(); @@ -194,44 +212,73 @@ impl KvsBackend for JsonBackend { hash_bytes[3], ]); if hash_kvs != file_hash { + error!( + "Hash mismatch, KVS file: {:?}, hash file: {:?}", + kvs_path, hash_path + ); return Err(ErrorCode::ValidationFailed); } } else { + error!("Invalid hash length: {:?}", hash_path); return Err(ErrorCode::ValidationFailed); } } - Err(e) => return Err(e.into()), + Err(e) => { + error!("Failed to load hash file: {:?}", hash_path); + return Err(e.into()); + } }; // Cast from `JsonValue` to `KvsValue`. + debug!("Converting JSON values to KVS values"); let kvs_value = KvsValue::from(json_value); if let KvsValue::Object(kvs_map) = kvs_value { Ok(kvs_map) } else { + error!("Conversion from JSON to KVS failed"); Err(ErrorCode::JsonParserError) } } fn save_kvs(kvs_map: &KvsMap, kvs_path: &Path, hash_path: &Path) -> Result<(), ErrorCode> { - // Validate extensions. + // Check file path extensions. + debug!("Checking KVS file path: {:?}", kvs_path); if !Self::check_extension(kvs_path, "json") { + error!("Invalid KVS file path extension: {:?}", kvs_path); return Err(ErrorCode::KvsFileReadError); } + + debug!("Checking hash file path: {:?}", hash_path); if !Self::check_extension(hash_path, "hash") { + error!("Invalid hash file path extension: {:?}", hash_path); return Err(ErrorCode::KvsHashFileReadError); } // Cast from `KvsValue` to `JsonValue`. + debug!("Converting KVS values to JSON values"); let kvs_value = KvsValue::Object(kvs_map.clone()); let json_value = JsonValue::from(kvs_value); // Stringify `JsonValue` and save to KVS file. - let json_str = Self::stringify(&json_value)?; - fs::write(kvs_path, &json_str)?; + debug!("Stringifying KVS file: {:?}", kvs_path); + let json_str = Self::stringify(&json_value).inspect_err(|_e| { + error!("Failed to stringify KVS file content: {:?}", kvs_path); + })?; + + debug!("Saving KVS file: {:?}", kvs_path); + fs::write(kvs_path, &json_str).inspect_err(|_e| { + error!("Failed to save KVS file: {:?}", kvs_path); + })?; // Generate hash and save to hash file. + debug!( + "Generating KVS hash, KVS file: {:?}, hash file: {:?}", + kvs_path, hash_path + ); let hash = adler32::RollingAdler32::from_buffer(json_str.as_bytes()).hash(); - fs::write(hash_path, hash.to_be_bytes())?; + fs::write(hash_path, hash.to_be_bytes()).inspect_err(|_e| { + error!("Failed to save hash file: {:?}", hash_path); + })?; Ok(()) } diff --git a/src/rust/rust_kvs/src/kvs.rs b/src/rust/rust_kvs/src/kvs.rs index 37e282ec..99077b84 100644 --- a/src/rust/rust_kvs/src/kvs.rs +++ b/src/rust/rust_kvs/src/kvs.rs @@ -10,17 +10,19 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error_code::ErrorCode; -use crate::kvs_api::{InstanceId, KvsApi, KvsDefaults, KvsLoad, SnapshotId}; +use crate::kvs_api::{DebugT, InstanceId, KvsApi, KvsDefaults, KvsLoad, SnapshotId}; use crate::kvs_backend::{KvsBackend, KvsPathResolver}; use crate::kvs_builder::KvsData; use crate::kvs_value::{KvsMap, KvsValue}; +use crate::log::{debug, error, warn}; use core::marker::PhantomData; use std::fs; use std::path::PathBuf; use std::sync::{Arc, Mutex}; /// KVS instance parameters. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "score-log", derive(mw_log::ScoreDebug))] pub struct KvsParameters { /// Instance ID. pub instance_id: InstanceId, @@ -117,7 +119,7 @@ impl GenericKvs {snap_name_new}"); + debug!("Rotating snapshots: {} -> {}", snap_name_old, snap_name_new); // Check snapshot and hash files exist. let snap_old_exists = snap_path_old.exists(); @@ -135,6 +137,7 @@ impl GenericKvs KvsApi fn reset_key(&self, key: &str) -> Result<(), ErrorCode> { let mut data = self.data.lock()?; if !data.defaults_map.contains_key(key) { - eprintln!("error: resetting key without a default value"); + error!("Resetting key without a default value: {}", key); return Err(ErrorCode::KeyDefaultNotFound); } @@ -220,7 +223,7 @@ impl KvsApi } else if let Some(value) = data.defaults_map.get(key) { Ok(value.clone()) } else { - eprintln!("error: get_value could not find key: {key}"); + error!("Key not found: {}", key); Err(ErrorCode::KeyNotFound) } } @@ -243,17 +246,15 @@ impl KvsApi /// * `ErrorCode::KeyNotFound`: Key wasn't found in KVS nor in defaults fn get_value_as(&self, key: &str) -> Result where - for<'a> T: TryFrom<&'a KvsValue> + core::clone::Clone, - for<'a> >::Error: core::fmt::Debug, + for<'a> T: TryFrom<&'a KvsValue>, + for<'a> >::Error: DebugT, { let data = self.data.lock()?; if let Some(value) = data.kvs_map.get(key) { match T::try_from(value) { Ok(value) => Ok(value), Err(err) => { - eprintln!( - "error: get_value could not convert KvsValue from KVS store: {err:#?}" - ); + error!("Failed to convert KVS value: {:#?}", err); Err(ErrorCode::ConversionFailed) } } @@ -262,15 +263,12 @@ impl KvsApi match T::try_from(value) { Ok(value) => Ok(value), Err(err) => { - eprintln!( - "error: get_value could not convert KvsValue from default store: {err:#?}" - ); + error!("Failed to convert default value: {:#?}", err); Err(ErrorCode::ConversionFailed) } } } else { - eprintln!("error: get_value could not find key: {key}"); - + error!("Key not found: {}", key); Err(ErrorCode::KeyNotFound) } } @@ -292,6 +290,7 @@ impl KvsApi if let Some(value) = data.defaults_map.get(key) { Ok(value.clone()) } else { + error!("Key not found: {}", key); Err(ErrorCode::KeyNotFound) } } @@ -316,6 +315,7 @@ impl KvsApi } else if data.defaults_map.contains_key(key) { Ok(true) } else { + error!("Key not found: {}", key); Err(ErrorCode::KeyNotFound) } } @@ -353,6 +353,7 @@ impl KvsApi if data.kvs_map.remove(key).is_some() { Ok(()) } else { + error!("Key not found: {}", key); Err(ErrorCode::KeyNotFound) } } @@ -372,12 +373,12 @@ impl KvsApi /// * `ErrorCode::UnmappedError`: Unmapped error fn flush(&self) -> Result<(), ErrorCode> { if self.snapshot_max_count() == 0 { - eprintln!("warn: snapshot_max_count == 0, flush ignored"); + warn!("snapshot_max_count == 0, flush ignored"); return Ok(()); } self.snapshot_rotate().map_err(|e| { - eprintln!("error: snapshot_rotate failed: {e:?}"); + error!("Failed to rotate snapshots: {:?}", e); e })?; let snapshot_id = SnapshotId(0); @@ -394,7 +395,7 @@ impl KvsApi let data = self.data.lock()?; Backend::save_kvs(&data.kvs_map, &kvs_path, &hash_path).map_err(|e| { - eprintln!("error: save_kvs failed: {e:?}"); + error!("Failed to save snapshot: {:?}", e); e })?; Ok(()) @@ -454,12 +455,12 @@ impl KvsApi let mut data = self.data.lock()?; // fail if the snapshot ID is the current KVS if snapshot_id == SnapshotId(0) { - eprintln!("error: tried to restore current KVS as snapshot"); + error!("Restoring current KVS snapshot is not allowed"); return Err(ErrorCode::InvalidSnapshotId); } if self.snapshot_count() < snapshot_id.0 { - eprintln!("error: tried to restore a non-existing snapshot"); + error!("Unable to restore non-existing snapshot"); return Err(ErrorCode::InvalidSnapshotId); } @@ -473,7 +474,10 @@ impl KvsApi self.parameters.instance_id, snapshot_id, ); - data.kvs_map = Backend::load_kvs(&kvs_path, &hash_path)?; + data.kvs_map = Backend::load_kvs(&kvs_path, &hash_path).map_err(|e| { + error!("Failed to load snapshot: {:?}", e); + e + })?; Ok(()) } @@ -493,6 +497,7 @@ impl KvsApi snapshot_id, ); if !path.exists() { + error!("File not found: {:?}", path); Err(ErrorCode::FileNotFound) } else { Ok(path) @@ -514,6 +519,7 @@ impl KvsApi snapshot_id, ); if !path.exists() { + error!("File not found: {:?}", path); Err(ErrorCode::FileNotFound) } else { Ok(path) diff --git a/src/rust/rust_kvs/src/kvs_api.rs b/src/rust/rust_kvs/src/kvs_api.rs index cef6b7c1..b0dc879c 100644 --- a/src/rust/rust_kvs/src/kvs_api.rs +++ b/src/rust/rust_kvs/src/kvs_api.rs @@ -11,15 +11,20 @@ use crate::error_code::ErrorCode; use crate::kvs_value::KvsValue; -use core::fmt; use std::path::PathBuf; +#[cfg(not(feature = "score-log"))] +pub use core::fmt::Debug as DebugT; +#[cfg(feature = "score-log")] +pub use mw_log::fmt::ScoreDebug as DebugT; + /// Instance ID #[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "score-log", derive(mw_log::ScoreDebug))] pub struct InstanceId(pub usize); -impl fmt::Display for InstanceId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl core::fmt::Display for InstanceId { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "{}", self.0) } } @@ -32,10 +37,11 @@ impl From for usize { /// Snapshot ID #[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "score-log", derive(mw_log::ScoreDebug))] pub struct SnapshotId(pub usize); -impl fmt::Display for SnapshotId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl core::fmt::Display for SnapshotId { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "{}", self.0) } } @@ -48,6 +54,7 @@ impl From for usize { /// Defaults handling mode. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "score-log", derive(mw_log::ScoreDebug))] pub enum KvsDefaults { /// Defaults are not loaded. Ignored, @@ -61,6 +68,7 @@ pub enum KvsDefaults { /// KVS load mode. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "score-log", derive(mw_log::ScoreDebug))] pub enum KvsLoad { /// KVS is not loaded. Ignored, @@ -80,8 +88,8 @@ pub trait KvsApi { fn get_value(&self, key: &str) -> Result; fn get_value_as(&self, key: &str) -> Result where - for<'a> T: TryFrom<&'a KvsValue> + Clone, - for<'a> >::Error: core::fmt::Debug; + for<'a> T: TryFrom<&'a KvsValue>, + for<'a> >::Error: DebugT; fn get_default_value(&self, key: &str) -> Result; fn is_value_default(&self, key: &str) -> Result; fn set_value, J: Into>( diff --git a/src/rust/rust_kvs/src/kvs_builder.rs b/src/rust/rust_kvs/src/kvs_builder.rs index a1b01004..79e3c9ba 100644 --- a/src/rust/rust_kvs/src/kvs_builder.rs +++ b/src/rust/rust_kvs/src/kvs_builder.rs @@ -14,6 +14,7 @@ use crate::kvs::{GenericKvs, KvsParameters}; use crate::kvs_api::{InstanceId, KvsDefaults, KvsLoad, SnapshotId}; use crate::kvs_backend::{KvsBackend, KvsPathResolver}; use crate::kvs_value::KvsMap; +use crate::log::{debug, error, info, trace}; use core::marker::PhantomData; use std::path::PathBuf; use std::sync::{Arc, LazyLock, Mutex, MutexGuard, PoisonError}; @@ -32,7 +33,8 @@ pub(crate) struct KvsData { } impl From>> for ErrorCode { - fn from(_cause: PoisonError>) -> Self { + fn from(cause: PoisonError>) -> Self { + error!("KVS data lock failed: {:?}", cause); ErrorCode::MutexLockFailed } } @@ -50,7 +52,8 @@ static KVS_POOL: LazyLock; KVS_MAX_INSTANCES]>> = LazyLock::new(|| Mutex::new([const { None }; KVS_MAX_INSTANCES])); impl From; KVS_MAX_INSTANCES]>>> for ErrorCode { - fn from(_cause: PoisonError; KVS_MAX_INSTANCES]>>) -> Self { + fn from(cause: PoisonError; KVS_MAX_INSTANCES]>>) -> Self { + error!("KVS instance pool lock failed: {:?}", cause); ErrorCode::MutexLockFailed } } @@ -158,6 +161,7 @@ impl GenericKvsBuilder Self { + trace!("\"defaults\" set to {:?}", mode); self.parameters.defaults = Some(mode); self } @@ -170,6 +174,7 @@ impl GenericKvsBuilder Self { + trace!("\"kvs_load\" set to {:?}", mode); self.parameters.kvs_load = Some(mode); self } @@ -182,7 +187,9 @@ impl GenericKvsBuilder>(mut self, dir: P) -> Self { - self.parameters.working_dir = Some(PathBuf::from(dir.into())); + let working_dir = PathBuf::from(dir.into()); + trace!("\"dir\" set to {:?}", working_dir); + self.parameters.working_dir = Some(working_dir); self } @@ -194,6 +201,7 @@ impl GenericKvsBuilder Self { + trace!("\"snapshot_max_count\" set to {:?}", snapshot_max_count); self.parameters.snapshot_max_count = Some(snapshot_max_count); self } @@ -218,8 +226,11 @@ impl GenericKvsBuilder match kvs_pool_entry { @@ -230,20 +241,29 @@ impl GenericKvsBuilder Ok(None), + None => { + debug!("KVS instance not found in instance pool"); + Ok(None) + } }, // Instance ID out of range. - None => Err(ErrorCode::InvalidInstanceId), + None => { + error!("Provided instance ID is out of range: {}", instance_id); + Err(ErrorCode::InvalidInstanceId) + } }?; // Return existing instance if initialized. if let Some(kvs_inner) = kvs_inner_option { + info!("Existing KVS instance: {}", instance_id); return Ok(GenericKvs::::new( kvs_inner.data.clone(), kvs_inner.parameters.clone(), @@ -257,6 +277,7 @@ impl GenericKvsBuilder GenericKvsBuilder GenericKvsBuilder entry, - None => return Err(ErrorCode::InvalidInstanceId), + None => { + // Unlikely - this was checked previously. + error!("Provided instance ID is out of range: {}", instance_id); + return Err(ErrorCode::InvalidInstanceId); + } }; let _ = kvs_pool_entry.insert(KvsInner { @@ -311,6 +338,7 @@ impl GenericKvsBuilder(&self, key: &str) -> Result where - for<'a> T: TryFrom<&'a KvsValue> + Clone, - for<'a> >::Error: core::fmt::Debug, + for<'a> T: TryFrom<&'a KvsValue>, + for<'a> >::Error: DebugT, { if self.fail { return Err(ErrorCode::UnmappedError); @@ -139,13 +140,13 @@ impl KvsApi for MockKvs { } Ok(()) } - fn get_kvs_filename(&self, _id: SnapshotId) -> Result { + fn get_kvs_filename(&self, _id: SnapshotId) -> Result { if self.fail { return Err(ErrorCode::UnmappedError); } Err(ErrorCode::FileNotFound) } - fn get_hash_filename(&self, _id: SnapshotId) -> Result { + fn get_hash_filename(&self, _id: SnapshotId) -> Result { if self.fail { return Err(ErrorCode::UnmappedError); } diff --git a/src/rust/rust_kvs/src/kvs_value.rs b/src/rust/rust_kvs/src/kvs_value.rs index d1ba9a09..cc689d93 100644 --- a/src/rust/rust_kvs/src/kvs_value.rs +++ b/src/rust/rust_kvs/src/kvs_value.rs @@ -16,6 +16,7 @@ pub type KvsMap = std::collections::HashMap; /// Key-value-storage value #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "score-log", derive(mw_log::ScoreDebug))] pub enum KvsValue { /// 32-bit signed integer I32(i32), diff --git a/src/rust/rust_kvs/src/lib.rs b/src/rust/rust_kvs/src/lib.rs index 544bea28..66c98a39 100644 --- a/src/rust/rust_kvs/src/lib.rs +++ b/src/rust/rust_kvs/src/lib.rs @@ -140,6 +140,7 @@ pub mod kvs_builder; pub mod kvs_mock; pub mod kvs_serialize; pub mod kvs_value; +mod log; use json_backend::JsonBackend; pub type KvsBuilder = kvs_builder::GenericKvsBuilder; diff --git a/src/rust/rust_kvs/src/log.rs b/src/rust/rust_kvs/src/log.rs new file mode 100644 index 00000000..752d1cc2 --- /dev/null +++ b/src/rust/rust_kvs/src/log.rs @@ -0,0 +1,24 @@ +// Copyright (c) 2025 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 + +//! This file exposes common logging interface for different front-ends. + +#![allow(unused_imports)] + +// Compile error if both `logging` and `score-log` features are enabled. +#[cfg(all(feature = "logging", feature = "score-log"))] +compile_error!("`logging` and `score-log` cannot be enabled at the same time."); + +#[cfg(feature = "logging")] +pub use log::{debug, error, info, trace, warn}; + +#[cfg(feature = "score-log")] +pub use mw_log::{debug, error, info, trace, warn}; diff --git a/src/rust/rust_kvs_tool/BUILD b/src/rust/rust_kvs_tool/BUILD index a28b0b8a..bb8ae5c8 100644 --- a/src/rust/rust_kvs_tool/BUILD +++ b/src/rust/rust_kvs_tool/BUILD @@ -18,11 +18,16 @@ rust_binary( srcs = [ "src/kvs_tool.rs", ], + crate_features = ["score-log"], crate_name = "rust_kvs_tool", + rustc_flags = [ + "-Clink-arg=-lstdc++", + "-Clink-arg=-lm", + "-Clink-arg=-lc", + ], visibility = ["//visibility:public"], - deps = all_crate_deps( - normal = True, - ) + [ + deps = [ "//src/rust/rust_kvs", - ], + "@score_logging//src/rust/mw_log_subscriber", + ] + all_crate_deps(normal = True), ) diff --git a/src/rust/rust_kvs_tool/Cargo.toml b/src/rust/rust_kvs_tool/Cargo.toml index 28900e3a..f07d5e13 100644 --- a/src/rust/rust_kvs_tool/Cargo.toml +++ b/src/rust/rust_kvs_tool/Cargo.toml @@ -3,7 +3,6 @@ name = "rust_kvs_tool" version.workspace = true edition.workspace = true - [[bin]] name = "kvs_tool" path = "src/kvs_tool.rs" @@ -13,6 +12,14 @@ path = "src/kvs_tool.rs" rust_kvs.workspace = true tinyjson.workspace = true pico-args.workspace = true +log = { version = "0.4.27", optional = true } +simple_logger = { version = "5.0.0", optional = true } + + +[features] +default = ["logging"] +score-log = [] +logging = ["log", "simple_logger"] [lints] diff --git a/src/rust/rust_kvs_tool/src/kvs_tool.rs b/src/rust/rust_kvs_tool/src/kvs_tool.rs index 6540e2a7..29b3445e 100644 --- a/src/rust/rust_kvs_tool/src/kvs_tool.rs +++ b/src/rust/rust_kvs_tool/src/kvs_tool.rs @@ -349,7 +349,7 @@ fn _getkvsfilename(kvs: Kvs, mut args: Arguments) -> Result<(), ErrorCode> { }; let snapshot_id = SnapshotId(snapshot_id as usize); let filename = kvs.get_kvs_filename(snapshot_id)?; - println!("KVS Filename: {}", filename.display()); + println!("KVS Filename: {:?}", filename); println!("----------------------"); Ok(()) } @@ -371,7 +371,7 @@ fn _gethashfilename(kvs: Kvs, mut args: Arguments) -> Result<(), ErrorCode> { }; let snapshot_id = SnapshotId(snapshot_id as usize); let filename = kvs.get_hash_filename(snapshot_id); - println!("Hash Filename: {}", filename?.display()); + println!("Hash Filename: {:?}", filename?); println!("----------------------"); Ok(()) } @@ -436,10 +436,24 @@ fn _createtestdata(kvs: Kvs) -> Result<(), ErrorCode> { Ok(()) } +fn init_logging() { + #[cfg(feature = "logging")] + simple_logger::SimpleLogger::new() + .with_level(log::LevelFilter::Warn) + .env() + .init() + .unwrap(); + + #[cfg(feature = "score-log")] + mw_log_subscriber::MwLoggerBuilder::new().set_as_default_logger(); +} + /// Main function to run the KVS tool command line interface. fn main() -> Result<(), ErrorCode> { let mut args = Arguments::from_env(); + init_logging(); + if args.contains(["-h", "--help"]) { const HELP: &str = r#" diff --git a/tests/python_test_cases/config/logging.json b/tests/python_test_cases/config/logging.json new file mode 100644 index 00000000..bd60e5cf --- /dev/null +++ b/tests/python_test_cases/config/logging.json @@ -0,0 +1,7 @@ +{ + "appId": "RUTS", + "appDesc": "Rust test scenarios", + "logMode": "kConsole", + "logLevel": "kVerbose", + "logLevelThresholdConsole": "kInfo" +} \ No newline at end of file diff --git a/tests/python_test_cases/pytest.ini b/tests/python_test_cases/pytest.ini index 46f32015..879529cc 100644 --- a/tests/python_test_cases/pytest.ini +++ b/tests/python_test_cases/pytest.ini @@ -23,4 +23,6 @@ markers = DerivationTechnique ; Additional environment variables -env = D:RUST_BACKTRACE = 1 +env = + D:RUST_BACKTRACE = 1 + D:MW_LOG_CONFIG_FILE = config/logging.json diff --git a/tests/python_test_cases/tests/test_cit_default_values.py b/tests/python_test_cases/tests/test_cit_default_values.py index ec681dab..734fe701 100644 --- a/tests/python_test_cases/tests/test_cit_default_values.py +++ b/tests/python_test_cases/tests/test_cit_default_values.py @@ -309,7 +309,7 @@ def test_invalid( assert defaults_file is not None assert results.return_code == ResultCode.PANIC assert results.stderr is not None - pattern = r'error: file ".*" could not be read: JsonParserError' + pattern = r'file ".*" could not be read: JsonParserError' assert re.findall(pattern, results.stderr) is not None @@ -348,7 +348,7 @@ def test_config(self, temp_dir: Path, defaults: str) -> dict[str, Any]: def test_invalid(self, results: ScenarioResult) -> None: assert results.return_code == ResultCode.PANIC assert results.stderr is not None - pattern = r'error: file ".*" could not be read: KvsFileReadError' + pattern = r'file ".*" could not be read: KvsFileReadError' assert re.findall(pattern, results.stderr) is not None diff --git a/tests/python_test_cases/tests/test_cit_snapshots.py b/tests/python_test_cases/tests/test_cit_snapshots.py index b8440a31..b704edc4 100644 --- a/tests/python_test_cases/tests/test_cit_snapshots.py +++ b/tests/python_test_cases/tests/test_cit_snapshots.py @@ -213,8 +213,10 @@ def test_error( ): assert results.return_code == ResultCode.SUCCESS - assert results.stderr is not None - assert "error: tried to restore current KVS as snapshot" in results.stderr + # TODO: Restore 'stderr' capture for error logs. + # 'mw_log' prints to 'stdout'. + # 'stderr' would be preferred for pytest-based tests. + assert "Restoring current KVS snapshot is not allowed" in results.stdout result_log = logs_info_level.find_log("result") assert result_log is not None @@ -256,8 +258,10 @@ def test_error( ): assert results.return_code == ResultCode.SUCCESS - assert results.stderr is not None - assert "error: tried to restore a non-existing snapshot" in results.stderr + # TODO: Restore 'stderr' capture for error logs. + # 'mw_log' prints to 'stdout'. + # 'stderr' would be preferred for pytest-based tests. + assert "Unable to restore non-existing snapshot" in results.stdout result_log = logs_info_level.find_log("result") assert result_log is not None diff --git a/tests/rust_test_scenarios/BUILD b/tests/rust_test_scenarios/BUILD index 1e50658a..0789d7f2 100644 --- a/tests/rust_test_scenarios/BUILD +++ b/tests/rust_test_scenarios/BUILD @@ -16,10 +16,15 @@ load("@score_persistency_crates//:defs.bzl", "all_crate_deps") rust_binary( name = "rust_test_scenarios", srcs = glob(["src/**/*.rs"]), + crate_features = ["score-log"], + rustc_flags = [ + "-Clink-arg=-lstdc++", + "-Clink-arg=-lm", + "-Clink-arg=-lc", + ], visibility = ["//tests/python_test_cases:__pkg__"], - deps = - [ - "//src/rust/rust_kvs", - "@score_persistency_crates//:tinyjson", - ] + all_crate_deps(normal = True), + deps = [ + "//src/rust/rust_kvs", + "@score_logging//src/rust/mw_log_subscriber", + ] + all_crate_deps(normal = True), ) diff --git a/tests/rust_test_scenarios/Cargo.toml b/tests/rust_test_scenarios/Cargo.toml index 98922eea..ba8f8538 100644 --- a/tests/rust_test_scenarios/Cargo.toml +++ b/tests/rust_test_scenarios/Cargo.toml @@ -5,13 +5,21 @@ edition.workspace = true [dependencies] -rust_kvs.workspace = true +rust_kvs = { workspace = true, features = ["logging"] } tinyjson.workspace = true tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["json"] } serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" test_scenarios_rust = { git = "https://github.com/qorix-group/testing_tools.git", tag = "v0.2.0" } +log = { version = "0.4.27", optional = true } +simple_logger = { version = "5.0.0", optional = true } + + +[features] +default = ["logging"] +score-log = [] +logging = ["log", "simple_logger"] [lints] diff --git a/tests/rust_test_scenarios/src/main.rs b/tests/rust_test_scenarios/src/main.rs index 28e80f6a..c039e62d 100644 --- a/tests/rust_test_scenarios/src/main.rs +++ b/tests/rust_test_scenarios/src/main.rs @@ -7,8 +7,21 @@ mod test_basic; use crate::cit::cit_scenario_group; use crate::test_basic::BasicScenario; +fn init_logging() { + #[cfg(feature = "logging")] + simple_logger::SimpleLogger::new() + .with_level(log::LevelFilter::Warn) + .env() + .init() + .unwrap(); + + #[cfg(feature = "score-log")] + mw_log_subscriber::MwLoggerBuilder::new().set_as_default_logger(); +} + fn main() { let raw_arguments: Vec = std::env::args().collect(); + init_logging(); // Basic group. let basic_scenario = Box::new(BasicScenario);