diff --git a/score/kvs/docs/detailed_design/class_diagram.puml b/score/kvs/docs/detailed_design/class_diagram.puml index 78b916d6f..ec41a1512 100644 --- a/score/kvs/docs/detailed_design/class_diagram.puml +++ b/score/kvs/docs/detailed_design/class_diagram.puml @@ -40,7 +40,7 @@ package "kvs_builder" { package "kvs_api" { +interface KvsApi { +reset() - +reset_key(key : string) + +set_value_to_default(key : string) +get_all_keys() : list +key_exists(key : string) : bool +get_value(key : string) : KvsValue @@ -66,7 +66,7 @@ package "kvs" { +parameters() : KvsParameters +reset() - +reset_key(key : string) + +set_value_to_default(key : string) +get_all_keys() : list +key_exists(key : string) : bool +get_value(key : string) : KvsValue diff --git a/score/kvs/docs/detailed_design/class_diagram_cpp.puml b/score/kvs/docs/detailed_design/class_diagram_cpp.puml index 9e67f82bf..efcb70fc4 100644 --- a/score/kvs/docs/detailed_design/class_diagram_cpp.puml +++ b/score/kvs/docs/detailed_design/class_diagram_cpp.puml @@ -47,7 +47,7 @@ interface IKvsBackend <> { interface IKvs <> { + Reset() : Result - + ResetKey(key : string) : Result + + SetValueToDefault(key : string) : Result + GetAllKeys() : Result> + KeyExists(key : string) : Result + GetValue(key : string) : Result @@ -104,7 +104,7 @@ class JsonBackend <> { class KvsMock <> { + Reset() : Result - + ResetKey(key : string) : Result + + SetValueToDefault(key : string) : Result + GetAllKeys() : Result> + KeyExists(key : string) : Result + GetValue(key : string) : Result @@ -128,7 +128,7 @@ class Kvs <> { - backend : IKvsBackend __ + Reset() : Result - + ResetKey(key : string) : Result + + SetValueToDefault(key : string) : Result + GetAllKeys() : Result> + KeyExists(key : string) : Result + GetValue(key : string) : Result diff --git a/score/kvs/error.cpp b/score/kvs/error.cpp index 71818ab59..d0cc214b7 100644 --- a/score/kvs/error.cpp +++ b/score/kvs/error.cpp @@ -55,8 +55,6 @@ std::string_view KvsErrorDomain::MessageFor(const score::result::ErrorCode& code return "Authentication failed"; case ErrorCode::kKeyNotFound: return "Key not found"; - case ErrorCode::kKeyDefaultNotFound: - return "Key default value not found"; case ErrorCode::kSerializationFailed: return "Serialization failed"; case ErrorCode::kInvalidSnapshotId: diff --git a/score/kvs/error.h b/score/kvs/error.h index 20125f092..6de0a185c 100644 --- a/score/kvs/error.h +++ b/score/kvs/error.h @@ -68,9 +68,6 @@ enum class ErrorCode : score::result::ErrorCode /// Key not found. kKeyNotFound = 14, - /// Key default value not found. - kKeyDefaultNotFound = 15, - /// Serialization failed. kSerializationFailed = 16, @@ -121,8 +118,6 @@ enum class ErrorCode : score::result::ErrorCode [[deprecated("Use kAuthenticationFailed instead. This name is removed in a future release.")]] = kAuthenticationFailed, KeyNotFound [[deprecated("Use kKeyNotFound instead. This name is removed in a future release.")]] = kKeyNotFound, - KeyDefaultNotFound [[deprecated("Use kKeyDefaultNotFound instead. This name is removed in a future release.")]] = - kKeyDefaultNotFound, SerializationFailed [[deprecated("Use kSerializationFailed instead. This name is removed in a future release.")]] = kSerializationFailed, InvalidSnapshotId [[deprecated("Use kInvalidSnapshotId instead. This name is removed in a future release.")]] = diff --git a/score/kvs/kvs.cpp b/score/kvs/kvs.cpp index c97218e8d..324c2aaae 100644 --- a/score/kvs/kvs.cpp +++ b/score/kvs/kvs.cpp @@ -261,21 +261,30 @@ score::Result Kvs::GetDefaultValue(const std::string_view key) const n return search->second; } -score::Result Kvs::ResetKey(const std::string_view key) noexcept +score::Result Kvs::SetValueToDefault(const std::string_view key) noexcept { - std::unique_lock lock_kvs{kvs_mutex_, std::try_to_lock}; - if (!lock_kvs.owns_lock()) + // Validate key. + if (!IsKeyValid(key)) { - return score::MakeUnexpected(ErrorCode::kMutexLockFailed); + logger_->LogError() << "Provided key is not valid" << key; + return score::MakeUnexpected(ErrorCode::kInvalidKey); } - if (default_values_.find(std::string(key)) == default_values_.end()) + // Get a default value. + auto default_value_result{GetDefaultValue(key)}; + if (!default_value_result.has_value()) { - return score::MakeUnexpected(ErrorCode::kKeyDefaultNotFound); + return score::MakeUnexpected(static_cast(*default_value_result.error())); + } + + // Set value. + std::unique_lock lock{kvs_mutex_, std::try_to_lock}; + if (!lock.owns_lock()) + { + return score::MakeUnexpected(ErrorCode::kMutexLockFailed); } - // Return value ignored: a key that was never written needs no reset. - score::cpp::ignore = kvs_.erase(std::string(key)); + kvs_.insert_or_assign(std::string(key), std::move(*default_value_result)); return {}; } diff --git a/score/kvs/kvs.h b/score/kvs/kvs.h index 68708a826..c15097bfe 100644 --- a/score/kvs/kvs.h +++ b/score/kvs/kvs.h @@ -229,15 +229,13 @@ class Kvs final /// @return The default value on success, or an ErrorCode on failure. score::Result GetDefaultValue(const std::string_view key) const noexcept; - /// @brief Resets a specified key to its default value. + /// @brief Sets a specified key to its default value. /// - /// If no default value is available, it returns an ErrorCode and doesn't delete the key. - /// If no key was ever written, but a default value is available, it returns successfully. - /// If a key was written and it has a default value, it deletes the written key. + /// If no default value is available, it returns an ErrorCode. /// - /// @param key The key to be reset to its default value. + /// @param key The key to be set to its default value. /// @return Nothing on success, or an ErrorCode on failure. - score::Result ResetKey(const std::string_view key) noexcept; + score::Result SetValueToDefault(const std::string_view key) noexcept; /// @brief Checks if the specified key wasn't set yet and uses its default value. /// @param key The key to check. @@ -381,13 +379,6 @@ class Kvs final return GetDefaultValue(key); } - /// @deprecated Use `ResetKey()` instead. - [[deprecated("Use ResetKey() instead. This name is removed in a future release.")]] - score::Result reset_key(const std::string_view key) noexcept - { - return ResetKey(key); - } - /// @deprecated Use `IsValueDefault()` instead. [[deprecated("Use IsValueDefault() instead. This name is removed in a future release.")]] score::Result is_value_default(const std::string_view key) const noexcept diff --git a/score/kvs/kvs_deprecated_api_test.cpp b/score/kvs/kvs_deprecated_api_test.cpp index 26da81ff9..400eb30b6 100644 --- a/score/kvs/kvs_deprecated_api_test.cpp +++ b/score/kvs/kvs_deprecated_api_test.cpp @@ -46,7 +46,6 @@ static_assert(static_cast(ErrorCode::kOutOfStorageSpac static_assert(static_cast(ErrorCode::kQuotaExceeded) == 12, ""); static_assert(static_cast(ErrorCode::kAuthenticationFailed) == 13, ""); static_assert(static_cast(ErrorCode::kKeyNotFound) == 14, ""); -static_assert(static_cast(ErrorCode::kKeyDefaultNotFound) == 15, ""); static_assert(static_cast(ErrorCode::kSerializationFailed) == 16, ""); static_assert(static_cast(ErrorCode::kInvalidSnapshotId) == 17, ""); static_assert(static_cast(ErrorCode::kConversionFailed) == 18, ""); @@ -97,7 +96,6 @@ static_assert(ErrorCode::OutOfStorageSpace == ErrorCode::kOutOfStorageSpace, "") static_assert(ErrorCode::QuotaExceeded == ErrorCode::kQuotaExceeded, ""); static_assert(ErrorCode::AuthenticationFailed == ErrorCode::kAuthenticationFailed, ""); static_assert(ErrorCode::KeyNotFound == ErrorCode::kKeyNotFound, ""); -static_assert(ErrorCode::KeyDefaultNotFound == ErrorCode::kKeyDefaultNotFound, ""); static_assert(ErrorCode::SerializationFailed == ErrorCode::kSerializationFailed, ""); static_assert(ErrorCode::InvalidSnapshotId == ErrorCode::kInvalidSnapshotId, ""); static_assert(ErrorCode::ConversionFailed == ErrorCode::kConversionFailed, ""); @@ -227,11 +225,6 @@ TEST(kvs_deprecated_api, kvs_write_wrappers) EXPECT_EQ(std::get(kvs.GetValue("old_key").value().GetValue()), 1); EXPECT_EQ(std::get(kvs.GetValue("new_key").value().GetValue()), 1); - ASSERT_TRUE(kvs.SetValue("default", KvsValue(9))); - ASSERT_FALSE(kvs.IsValueDefault("default").value()); - ASSERT_TRUE(kvs.reset_key("default")); - EXPECT_TRUE(kvs.IsValueDefault("default").value()); - ASSERT_TRUE(kvs.remove_key("old_key")); EXPECT_FALSE(kvs.KeyExists("old_key").value()); EXPECT_TRUE(kvs.KeyExists("new_key").value()); diff --git a/score/kvs/kvs_error_test.cpp b/score/kvs/kvs_error_test.cpp index 23799cb32..e9c5f6cd5 100644 --- a/score/kvs/kvs_error_test.cpp +++ b/score/kvs/kvs_error_test.cpp @@ -40,7 +40,6 @@ TEST(kvs_MessageFor, MessageFor) {ErrorCode::kQuotaExceeded, "Quota exceeded"}, {ErrorCode::kAuthenticationFailed, "Authentication failed"}, {ErrorCode::kKeyNotFound, "Key not found"}, - {ErrorCode::kKeyDefaultNotFound, "Key default value not found"}, {ErrorCode::kSerializationFailed, "Serialization failed"}, {ErrorCode::kInvalidSnapshotId, "Invalid snapshot ID"}, {ErrorCode::kConversionFailed, "Conversion failed"}, diff --git a/score/kvs/kvs_test.cpp b/score/kvs/kvs_test.cpp index 143d08db4..57c46d9f7 100644 --- a/score/kvs/kvs_test.cpp +++ b/score/kvs/kvs_test.cpp @@ -840,7 +840,7 @@ TEST(kvs_get_default_value, get_default_value_failure) CleanupEnvironment(); } -TEST(kvs_reset_key, reset_key_success) +TEST(kvs_set_value_to_default, set_value_to_default_success) { PrepareEnvironment(); seed_defaults(R"({"default": {"t": "i32", "v": 5}, "kvs": {"t": "f64", "v": 42.0}})"); @@ -857,25 +857,35 @@ TEST(kvs_reset_key, reset_key_success) auto exists_result{result.value().KeyExists("kvs")}; ASSERT_TRUE(exists_result); ASSERT_TRUE(exists_result.value()); - // Reset a key. - auto reset_key_result{result.value().ResetKey("kvs")}; - EXPECT_TRUE(reset_key_result); + // Set a written key to its default value. + auto set_value_to_default_result{result.value().SetValueToDefault("kvs")}; + EXPECT_TRUE(set_value_to_default_result); exists_result = result.value().KeyExists("kvs"); ASSERT_TRUE(exists_result); - EXPECT_FALSE(exists_result.value()); - auto is_default_result{result.value().IsValueDefault("kvs")}; - ASSERT_TRUE(is_default_result); - EXPECT_TRUE(is_default_result.value()); - EXPECT_TRUE(result.value().GetDefaultValue("kvs")); + EXPECT_TRUE(exists_result.value()); + auto value_result{result.value().GetValue("kvs")}; + ASSERT_TRUE(value_result); + ASSERT_EQ(value_result.value().GetType(), KvsValue::Type::kF64); + EXPECT_EQ(std::get(value_result.value().GetValue()), 42.0); - // Reset a non written key which has default value. - reset_key_result = result.value().ResetKey("default"); - EXPECT_TRUE(reset_key_result); + // Set a non written key which has default value. + exists_result = result.value().KeyExists("default"); + ASSERT_TRUE(exists_result); + ASSERT_FALSE(exists_result.value()); + set_value_to_default_result = result.value().SetValueToDefault("default"); + EXPECT_TRUE(set_value_to_default_result); + exists_result = result.value().KeyExists("default"); + ASSERT_TRUE(exists_result); + EXPECT_TRUE(exists_result.value()); + value_result = result.value().GetValue("default"); + ASSERT_TRUE(value_result); + ASSERT_EQ(value_result.value().GetType(), KvsValue::Type::kI32); + EXPECT_EQ(std::get(value_result.value().GetValue()), 5); CleanupEnvironment(); } -TEST(kvs_reset_key, reset_key_failure) +TEST(kvs_set_value_to_default, set_value_to_default_failure) { PrepareEnvironment(); @@ -888,12 +898,12 @@ TEST(kvs_reset_key, reset_key_failure) kDefaultMaxSnapshots)}; ASSERT_TRUE(result); - // Reset a non-existing key. - auto reset_key_result{result.value().ResetKey("non_existing_key")}; - EXPECT_FALSE(reset_key_result); - EXPECT_EQ(reset_key_result.error(), ErrorCode::kKeyDefaultNotFound); + // Set a non-existing key to default. + auto set_value_to_default_result{result.value().SetValueToDefault("non_existing_key")}; + EXPECT_FALSE(set_value_to_default_result); + EXPECT_EQ(set_value_to_default_result.error(), ErrorCode::kKeyNotFound); - // Reset a key without default value. + // Set a key without default value. result = Kvs::Open(kInstanceId, kSnapshotId, KvsDefaults::kRequired, @@ -906,9 +916,9 @@ TEST(kvs_reset_key, reset_key_failure) auto get_default_result{result.value().GetDefaultValue("kvs")}; ASSERT_FALSE(get_default_result); EXPECT_EQ(get_default_result.error(), ErrorCode::kKeyNotFound); - reset_key_result = result.value().ResetKey("kvs"); - EXPECT_FALSE(reset_key_result); - EXPECT_EQ(reset_key_result.error(), ErrorCode::kKeyDefaultNotFound); + set_value_to_default_result = result.value().SetValueToDefault("kvs"); + EXPECT_FALSE(set_value_to_default_result); + EXPECT_EQ(set_value_to_default_result.error(), ErrorCode::kKeyNotFound); // Mutex locked. result = Kvs::Open(kInstanceId, @@ -920,9 +930,42 @@ TEST(kvs_reset_key, reset_key_failure) kDefaultMaxSnapshots); ASSERT_TRUE(result); std::unique_lock lock{result.value().kvs_mutex_}; - reset_key_result = result.value().ResetKey("kvs"); - EXPECT_FALSE(reset_key_result); - EXPECT_EQ(static_cast(*reset_key_result.error()), ErrorCode::kMutexLockFailed); + set_value_to_default_result = result.value().SetValueToDefault("default"); + EXPECT_FALSE(set_value_to_default_result); + EXPECT_EQ(static_cast(*set_value_to_default_result.error()), ErrorCode::kMutexLockFailed); + + CleanupEnvironment(); +} + +TEST(kvs_set_value_to_default, set_value_to_default_failure_invalid_key) +{ + PrepareEnvironment(); + auto result{Kvs::Open(kInstanceId, + kSnapshotId, + KvsDefaults::kRequired, + KvsLoad::kRequired, + std::string(kDataDir), + std::nullopt, + kDefaultMaxSnapshots)}; + ASSERT_TRUE(result); + + // Keys are validated before the default value lookup. + // None of these keys has a default value, so a lookup first would return kKeyNotFound. + std::vector invalid_keys{InvalidCharacterKeys()}; + invalid_keys.emplace_back(""); + invalid_keys.emplace_back(kMaxKeyLengthBytes + 1U, 'k'); + const auto keys_before{result.value().GetAllKeys()}; + ASSERT_TRUE(keys_before); + for (const auto& key : invalid_keys) + { + auto set_value_to_default_result{result.value().SetValueToDefault(key)}; + ASSERT_FALSE(set_value_to_default_result) << "key: " << key; + EXPECT_EQ(static_cast(*set_value_to_default_result.error()), ErrorCode::kInvalidKey) + << "key: " << key; + } + const auto keys_after{result.value().GetAllKeys()}; + ASSERT_TRUE(keys_after); + EXPECT_EQ(keys_after.value(), keys_before.value()); CleanupEnvironment(); } diff --git a/score/kvs/rust_kvs/error_code.rs b/score/kvs/rust_kvs/error_code.rs index f5f925271..1c4cc74dc 100644 --- a/score/kvs/rust_kvs/error_code.rs +++ b/score/kvs/rust_kvs/error_code.rs @@ -64,9 +64,6 @@ pub enum ErrorCode { /// Key not found KeyNotFound, - // Key has no default value - KeyDefaultNotFound, - /// Serialization failed SerializationFailed(String), diff --git a/score/kvs/rust_kvs/examples/defaults.rs b/score/kvs/rust_kvs/examples/defaults.rs index 38d2f60b1..a9b42a35d 100644 --- a/score/kvs/rust_kvs/examples/defaults.rs +++ b/score/kvs/rust_kvs/examples/defaults.rs @@ -12,7 +12,7 @@ // ******************************************************************************* //! Example for default values. //! - Creating KVS instance using `KvsBuilder` with `defaults` modes. -//! - Default-specific APIs: `get_default_value`, `is_value_default`. +//! - Default-specific APIs: `get_default_value`, `is_value_default`, `set_value_to_default`. //! - Key-value operations behavior on defaults available. use rust_kvs::prelude::*; @@ -109,7 +109,7 @@ fn main() -> Result<(), ErrorCode> { println!("All KVS keys: {all_keys:?}"); let k3_key = "k3"; - let k3_value = kvs.get_value(k3_key)?; + let k3_value = kvs.get_value(k3_key); println!("{k3_key:?} = {k3_value:?}"); if !kvs.key_exists(k3_key)? { @@ -120,15 +120,17 @@ fn main() -> Result<(), ErrorCode> { } { - println!("-> `reset_key` usage"); + println!("-> `set_value_to_default` usage"); let k1_key = "k1"; - kvs.reset_key(k1_key)?; - if !kvs.key_exists(k1_key)? { - println!("{k1_key} key not found"); + kvs.set_value_to_default(k1_key)?; + let k1_value = kvs.get_value(k1_key)?; + println!("{k1_key:?} = {k1_value:?}"); + if kvs.key_exists(k1_key)? { + println!("{k1_key} key exists"); } - if kvs.is_value_default(k1_key)? { - println!("{k1_key} default available"); + if !kvs.is_value_default(k1_key)? { + println!("{k1_key} is not default"); } println!(); diff --git a/score/kvs/rust_kvs/kvs.rs b/score/kvs/rust_kvs/kvs.rs index 4276c075c..be4882d7d 100644 --- a/score/kvs/rust_kvs/kvs.rs +++ b/score/kvs/rust_kvs/kvs.rs @@ -69,23 +69,34 @@ impl KvsApi for Kvs { Ok(()) } - /// Reset a key-value pair in the storage to its initial state + /// Sets a specified key to its default value. /// /// # Parameters - /// * 'key': Key being reset to default + /// * 'key': The key to be set to its default value. /// /// # Return Values - /// * Ok: Reset of the key-value pair was successful + /// * Ok: Set to a default value was successful /// * `ErrorCode::MutexLockFailed`: Mutex locking failed - /// * `ErrorCode::KeyDefaultNotFound`: Key has no default value - fn reset_key(&self, key: &str) -> Result<(), ErrorCode> { - let mut data = self.data.lock()?; - if !data.defaults_map.contains_key(key) { - error!("Resetting key without a default value: {}", key); - return Err(ErrorCode::KeyDefaultNotFound); + /// * `ErrorCode::KeyNotFound`: Key has no default value + fn set_value_to_default(&self, key: &str) -> Result<(), ErrorCode> { + // Validate key. + if !is_key_valid(key) { + error!("Provided key is not valid: {}", key); + return Err(ErrorCode::InvalidKey); } - let _ = data.kvs_map.remove(key); + // Get a default value. + let mut data = self.data.lock()?; + let default_value = match data.defaults_map.get(key) { + Some(value) => value.clone(), + None => { + error!("Setting a default value to a key without a default value: {}", key); + return Err(ErrorCode::KeyNotFound); + }, + }; + + // Set value. + data.kvs_map.insert(key.to_string(), default_value); Ok(()) } @@ -419,25 +430,54 @@ mod kvs_tests { #[cfg_attr(miri, ignore)] #[test] - fn test_reset_key() { + fn test_set_value_to_default() { let kvs = get_kvs( Box::new(MockBackend), KvsMap::from([ ("example1".to_string(), KvsValue::from("explicit_value")), ("example2".to_string(), KvsValue::from(true)), ]), - KvsMap::from([("example1".to_string(), KvsValue::from("default_value"))]), + KvsMap::from([ + ("example1".to_string(), KvsValue::from("default_value")), + ("example3".to_string(), KvsValue::from(123.4)), + ]), ); - kvs.reset_key("example1").unwrap(); + // Written key with a default value - default value is written. + kvs.set_value_to_default("example1").unwrap(); + assert_eq!(kvs.get_value_as::("example1").unwrap(), "default_value"); + assert!(!kvs.is_value_default("example1").unwrap()); + + // Not written key with a default value - default value is written. + kvs.set_value_to_default("example3").unwrap(); + assert_eq!(kvs.get_value_as::("example3").unwrap(), 123.4); + assert!(!kvs.is_value_default("example3").unwrap()); + + // Key without a default value - explicit value is kept. assert!(kvs - .get_value_as::("example1") + .set_value_to_default("example2") .is_err_and(|e| e == ErrorCode::KeyNotFound)); + assert!(kvs.get_value_as::("example2").unwrap()); + } - // TODO: determine why resetting entry without default value is an error. - assert!(kvs - .reset_key("example2") - .is_err_and(|e| e == ErrorCode::KeyDefaultNotFound)); + #[test] + fn test_set_value_to_default_invalid_key() { + let defaults_map = KvsMap::from_iter( + invalid_keys() + .into_iter() + .map(|key| (key, KvsValue::from("default_value"))), + ); + let kvs = get_kvs(Box::new(MockBackend), KvsMap::new(), defaults_map); + + // Keys are validated before the default value lookup. + for key in invalid_keys() { + assert!( + kvs.set_value_to_default(&key) + .is_err_and(|e| e == ErrorCode::InvalidKey), + "key: {key:?}" + ); + } + assert!(kvs.get_all_keys().unwrap().is_empty()); } #[test] diff --git a/score/kvs/rust_kvs/kvs_api.rs b/score/kvs/rust_kvs/kvs_api.rs index 2f1cb4776..7e08310e2 100644 --- a/score/kvs/rust_kvs/kvs_api.rs +++ b/score/kvs/rust_kvs/kvs_api.rs @@ -97,7 +97,7 @@ pub enum KvsLoad { pub trait KvsApi { fn reset(&self) -> Result<(), ErrorCode>; - fn reset_key(&self, key: &str) -> Result<(), ErrorCode>; + fn set_value_to_default(&self, key: &str) -> Result<(), ErrorCode>; fn get_all_keys(&self) -> Result, ErrorCode>; fn key_exists(&self, key: &str) -> Result; fn get_value(&self, key: &str) -> Result; diff --git a/score/kvs/rust_kvs/kvs_mock.rs b/score/kvs/rust_kvs/kvs_mock.rs index 146d5a9ed..2faee8857 100644 --- a/score/kvs/rust_kvs/kvs_mock.rs +++ b/score/kvs/rust_kvs/kvs_mock.rs @@ -44,17 +44,11 @@ impl KvsApi for MockKvs { self.map.lock().unwrap().clear(); Ok(()) } - fn reset_key(&self, key: &str) -> Result<(), ErrorCode> { + fn set_value_to_default(&self, _key: &str) -> Result<(), ErrorCode> { if self.fail { return Err(ErrorCode::UnmappedError); } - let mut map = self.map.lock().unwrap(); - if map.contains_key(key) { - map.remove(key); - Ok(()) - } else { - Err(ErrorCode::KeyDefaultNotFound) - } + Err(ErrorCode::KeyNotFound) } fn get_all_keys(&self) -> Result, ErrorCode> { if self.fail { @@ -136,6 +130,7 @@ impl KvsApi for MockKvs { #[cfg(test)] mod tests { + use crate::error_code::ErrorCode; use crate::kvs_api::{KvsApi, SnapshotId}; use crate::kvs_mock::MockKvs; use crate::kvs_value::KvsValue; @@ -148,6 +143,9 @@ mod tests { assert_eq!(kvs.get_value("a").unwrap(), KvsValue::from(1.0)); assert_eq!(kvs.get_all_keys().unwrap(), vec!["a".to_string()]); assert!(kvs.key_exists("a").unwrap()); + assert!(kvs + .set_value_to_default("a") + .is_err_and(|e| e == ErrorCode::KeyNotFound)); assert!(kvs.remove_key("a").is_ok()); assert!(!kvs.key_exists("a").unwrap()); assert_eq!(kvs.snapshot_count(), 0); @@ -167,7 +165,7 @@ mod tests { assert_eq!(kvs_fail.snapshot_count(), 9999); assert!(kvs_fail.flush().is_err()); assert!(kvs_fail.reset().is_err()); - assert!(kvs_fail.reset_key("a").is_err()); + assert!(kvs_fail.set_value_to_default("a").is_err()); assert!(kvs_fail.get_default_value("a").is_err()); assert!(kvs_fail.is_value_default("a").is_err()); assert!(kvs_fail.snapshot_restore(SnapshotId(0)).is_err()); diff --git a/score/kvs/rust_kvs/tests/test_scenarios/cit/default_values.rs b/score/kvs/rust_kvs/tests/test_scenarios/cit/default_values.rs index 7b0dee583..078d9ac38 100644 --- a/score/kvs/rust_kvs/tests/test_scenarios/cit/default_values.rs +++ b/score/kvs/rust_kvs/tests/test_scenarios/cit/default_values.rs @@ -186,17 +186,17 @@ impl Scenario for ResetAllKeys { } } -/// Reset single key. -struct ResetSingleKey; +/// Set single key to default. +struct SetValueToDefault; -impl Scenario for ResetSingleKey { +impl Scenario for SetValueToDefault { fn name(&self) -> &str { - "reset_single_key" + "set_value_to_default" } fn run(&self, input: &str) -> Result<(), String> { let num_values = 5; - let reset_index = 2; + let default_index = 2; // Create KVS instance with provided params. let params = KvsParameters::from_json(input).expect("Failed to parse parameters"); @@ -229,11 +229,11 @@ impl Scenario for ResetSingleKey { info!(key, value_is_default, current_value); } - // Reset single key. - kvs.reset_key(&key_values.get(reset_index).expect("Failed to read value").0) - .expect("Failed to reset key"); + // Set single key to default. + kvs.set_value_to_default(&key_values.get(default_index).expect("Failed to read value").0) + .expect("Failed to set value to default"); - // Get value parameters after reset. + // Get value parameters after set to default. for (key, _) in key_values.iter() { let value_is_default = value_is_default_str(&kvs, key); let current_value = current_value_str(&kvs, key); @@ -282,7 +282,7 @@ pub fn default_values_group() -> Box { Box::new(DefaultValues), Box::new(RemoveKey), Box::new(ResetAllKeys), - Box::new(ResetSingleKey), + Box::new(SetValueToDefault), Box::new(Checksum), ], vec![], diff --git a/score/kvs/tests/test_cases/tests/test_cit_default_values.py b/score/kvs/tests/test_cases/tests/test_cit_default_values.py index c5f36b791..f044a0b9e 100644 --- a/score/kvs/tests/test_cases/tests/test_cit_default_values.py +++ b/score/kvs/tests/test_cases/tests/test_cit_default_values.py @@ -428,6 +428,7 @@ def test_valid( @add_test_properties( partially_verifies=[ + "comp_req__kvs__value_reset", "comp_req__kvs__value_default", "comp_req__kvs__default_value_cfg", ], @@ -435,15 +436,15 @@ def test_valid( derivation_technique="requirements-analysis", ) @pytest.mark.parametrize("defaults", ["optional", "required"], scope="class") -class TestResetSingleKey(DefaultValuesScenario): - """Checks that resetting single key restores it to its default value.""" +class TestSetValueToDefault(DefaultValuesScenario): + """Checks that setting a single key to default writes its default value.""" NUM_VALUES = 5 - RESET_INDEX = 2 + DEFAULT_INDEX = 2 @pytest.fixture(scope="class") def scenario_name(self) -> str: - return "cit.default_values.reset_single_key" + return "cit.default_values.set_value_to_default" @pytest.fixture(scope="class") def test_config(self, temp_dir: Path, defaults: str, defaults_file: Path | None) -> dict[str, Any]: @@ -480,7 +481,7 @@ def test_valid( for i in range(self.NUM_VALUES): logs = logs_info_level.get_logs("key", value=f"test_number_{i}") - if i == self.RESET_INDEX: + if i == self.DEFAULT_INDEX: # Check values before set (no explicit value written yet, only a default). assert logs[0].value_is_default == "Ok(true)" assert logs[0].current_value == "Err(KeyNotFound)" @@ -489,9 +490,9 @@ def test_valid( assert logs[1].value_is_default == "Ok(false)" assert logs[1].current_value == f"Ok(F64({123.4 * i:.1f}))" - # Check values after reset (explicit value removed again). - assert logs[2].value_is_default == "Ok(true)" - assert logs[2].current_value == "Err(KeyNotFound)" + # Check values after set to default (default value written as explicit value). + assert logs[2].value_is_default == "Ok(false)" + assert logs[2].current_value == f"Ok(F64({432.1 * i:.1f}))" else: # Check values before set (no explicit value written yet, only a default). @@ -502,7 +503,7 @@ def test_valid( assert logs[1].value_is_default == "Ok(false)" assert logs[1].current_value == f"Ok(F64({123.4 * i:.1f}))" - # Check values after reset (not reset, explicit value still present). + # Check values after set to default (not set to default, explicit value still present). assert logs[2].value_is_default == "Ok(false)" assert logs[2].current_value == f"Ok(F64({123.4 * i:.1f}))" diff --git a/score/kvs/tests/test_scenarios/cit/default_values.cpp b/score/kvs/tests/test_scenarios/cit/default_values.cpp index 24229bddd..655a15b54 100644 --- a/score/kvs/tests/test_scenarios/cit/default_values.cpp +++ b/score/kvs/tests/test_scenarios/cit/default_values.cpp @@ -301,20 +301,20 @@ class ResetAllKeys final : public Scenario } }; -class ResetSingleKey final : public Scenario +class SetValueToDefault final : public Scenario { public: - ~ResetSingleKey() final = default; + ~SetValueToDefault() final = default; std::string name() const final { - return "reset_single_key"; + return "set_value_to_default"; } void run(const std::string& input) const final { const int num_values{5}; - const int reset_index{2}; + const int default_index{2}; // Create KVS instance with provided params. auto params{KvsParameters::FromJson(input)}; @@ -354,14 +354,14 @@ class ResetSingleKey final : public Scenario } } - // Reset single key. - auto reset_result{kvs.ResetKey(key_values[reset_index].first)}; - if (!reset_result) + // Set single key to default. + auto set_default_result{kvs.SetValueToDefault(key_values[default_index].first)}; + if (!set_default_result) { - throw std::runtime_error{"Failed to reset key"}; + throw std::runtime_error{"Failed to set value to default"}; } - // Use KVS APIs to get value_is_default and current_value after reset. + // Use KVS APIs to get value_is_default and current_value after set to default. for (const auto& [key, value] : key_values) { const std::string value_is_default{ValueIsDefaultStr(kvs, key)}; @@ -411,7 +411,7 @@ ScenarioGroup::Ptr DefaultValuesGroup() {std::make_shared(), std::make_shared(), std::make_shared(), - std::make_shared(), + std::make_shared(), std::make_shared()}, {}}}; }