|
11 | 11 |
|
12 | 12 | use crate::error_code::ErrorCode; |
13 | 13 | use crate::kvs_api::{InstanceId, SnapshotId}; |
14 | | -use crate::kvs_backend::KvsBackend; |
| 14 | +use crate::kvs_backend::{KvsBackend, KvsBackendFactory}; |
15 | 15 | use crate::kvs_value::{KvsMap, KvsValue}; |
16 | 16 | use std::collections::HashMap; |
17 | 17 | use std::fs; |
@@ -151,7 +151,7 @@ impl From<JsonGenerateError> for ErrorCode { |
151 | 151 | } |
152 | 152 |
|
153 | 153 | /// Builder for `JsonBackend`. |
154 | | -pub struct JsonBackendBuilder { |
| 154 | +pub(crate) struct JsonBackendBuilder { |
155 | 155 | working_dir: PathBuf, |
156 | 156 | snapshot_max_count: usize, |
157 | 157 | } |
@@ -190,7 +190,7 @@ impl Default for JsonBackendBuilder { |
190 | 190 |
|
191 | 191 | /// KVS backend implementation based on TinyJSON. |
192 | 192 | #[derive(Clone, PartialEq)] |
193 | | -pub struct JsonBackend { |
| 193 | +pub(crate) struct JsonBackend { |
194 | 194 | working_dir: PathBuf, |
195 | 195 | snapshot_max_count: usize, |
196 | 196 | } |
@@ -255,7 +255,7 @@ impl JsonBackend { |
255 | 255 | ext.is_some_and(|ep| ep.to_str().is_some_and(|es| es == extension)) |
256 | 256 | } |
257 | 257 |
|
258 | | - pub(super) fn load(kvs_path: &Path, hash_path: Option<&PathBuf>) -> Result<KvsMap, ErrorCode> { |
| 258 | + pub(crate) fn load(kvs_path: &Path, hash_path: Option<&PathBuf>) -> Result<KvsMap, ErrorCode> { |
259 | 259 | if !Self::check_extension(kvs_path, "json") { |
260 | 260 | return Err(ErrorCode::KvsFileReadError); |
261 | 261 | } |
@@ -299,7 +299,7 @@ impl JsonBackend { |
299 | 299 | } |
300 | 300 | } |
301 | 301 |
|
302 | | - pub(super) fn save( |
| 302 | + pub(crate) fn save( |
303 | 303 | kvs_map: &KvsMap, |
304 | 304 | kvs_path: &Path, |
305 | 305 | hash_path: Option<&PathBuf>, |
@@ -433,13 +433,41 @@ impl KvsBackend for JsonBackend { |
433 | 433 | } |
434 | 434 | } |
435 | 435 |
|
| 436 | +/// `JsonBackend` factory. |
| 437 | +pub(crate) struct JsonBackendFactory; |
| 438 | + |
| 439 | +impl KvsBackendFactory for JsonBackendFactory { |
| 440 | + fn create(&self, parameters: &KvsMap) -> Result<Box<dyn KvsBackend>, ErrorCode> { |
| 441 | + let mut builder = JsonBackendBuilder::new(); |
| 442 | + |
| 443 | + // Set working directory. |
| 444 | + if let Some(working_dir) = parameters.get("working_dir") { |
| 445 | + if let KvsValue::String(working_dir) = working_dir { |
| 446 | + builder = builder.working_dir(PathBuf::from(working_dir)); |
| 447 | + } else { |
| 448 | + return Err(ErrorCode::InvalidBackendParameters); |
| 449 | + } |
| 450 | + } |
| 451 | + |
| 452 | + // Set snapshot max count. |
| 453 | + if let Some(snapshot_max_count) = parameters.get("snapshot_max_count") { |
| 454 | + if let KvsValue::U64(snapshot_max_count) = snapshot_max_count { |
| 455 | + builder = builder.snapshot_max_count(*snapshot_max_count as usize); |
| 456 | + } else { |
| 457 | + return Err(ErrorCode::InvalidBackendParameters); |
| 458 | + } |
| 459 | + } |
| 460 | + |
| 461 | + Ok(Box::new(builder.build())) |
| 462 | + } |
| 463 | +} |
| 464 | + |
436 | 465 | #[cfg(test)] |
437 | 466 | mod json_value_to_kvs_value_conversion_tests { |
| 467 | + use crate::kvs_value::{KvsMap, KvsValue}; |
438 | 468 | use std::collections::HashMap; |
439 | 469 | use tinyjson::JsonValue; |
440 | 470 |
|
441 | | - use crate::prelude::{KvsMap, KvsValue}; |
442 | | - |
443 | 471 | #[test] |
444 | 472 | fn test_i32_ok() { |
445 | 473 | let jv = JsonValue::from(HashMap::from([ |
@@ -1356,3 +1384,59 @@ mod kvs_backend_tests { |
1356 | 1384 | assert!(result.is_err_and(|e| e == ErrorCode::InvalidSnapshotId)); |
1357 | 1385 | } |
1358 | 1386 | } |
| 1387 | + |
| 1388 | +#[cfg(test)] |
| 1389 | +mod kvs_backend_factory_tests { |
| 1390 | + use crate::error_code::ErrorCode; |
| 1391 | + use crate::json_backend::JsonBackendFactory; |
| 1392 | + use crate::kvs_backend::KvsBackendFactory; |
| 1393 | + use crate::kvs_value::{KvsMap, KvsValue}; |
| 1394 | + |
| 1395 | + #[test] |
| 1396 | + fn test_create_default_ok() { |
| 1397 | + let factory = JsonBackendFactory; |
| 1398 | + let params = KvsMap::new(); |
| 1399 | + let backend = factory.create(¶ms).unwrap(); |
| 1400 | + // `working_dir` is not exposed in the API. |
| 1401 | + assert_eq!(backend.snapshot_max_count(), 3); |
| 1402 | + } |
| 1403 | + |
| 1404 | + #[test] |
| 1405 | + fn test_create_params_ok() { |
| 1406 | + let factory = JsonBackendFactory; |
| 1407 | + let params = KvsMap::from([ |
| 1408 | + ( |
| 1409 | + "working_dir".to_string(), |
| 1410 | + KvsValue::String("/some/path/".to_string()), |
| 1411 | + ), |
| 1412 | + ("snapshot_max_count".to_string(), KvsValue::U64(1234)), |
| 1413 | + ]); |
| 1414 | + let backend = factory.create(¶ms).unwrap(); |
| 1415 | + // `working_dir` is not exposed in the API. |
| 1416 | + assert_eq!(backend.snapshot_max_count(), 1234); |
| 1417 | + } |
| 1418 | + |
| 1419 | + #[test] |
| 1420 | + fn test_create_working_dir_invalid_type() { |
| 1421 | + let factory = JsonBackendFactory; |
| 1422 | + let params = KvsMap::from([("working_dir".to_string(), KvsValue::Boolean(true))]); |
| 1423 | + let result = factory.create(¶ms); |
| 1424 | + assert!(result.is_err_and(|e| e == ErrorCode::InvalidBackendParameters)); |
| 1425 | + } |
| 1426 | + |
| 1427 | + #[test] |
| 1428 | + fn test_create_snapshot_max_count_invalid_type() { |
| 1429 | + let factory = JsonBackendFactory; |
| 1430 | + let params = KvsMap::from([("snapshot_max_count".to_string(), KvsValue::I32(-123))]); |
| 1431 | + let result = factory.create(¶ms); |
| 1432 | + assert!(result.is_err_and(|e| e == ErrorCode::InvalidBackendParameters)); |
| 1433 | + } |
| 1434 | + |
| 1435 | + #[test] |
| 1436 | + fn test_create_unknown_param_ok() { |
| 1437 | + let factory = JsonBackendFactory; |
| 1438 | + let params = KvsMap::from([("unknown_param".to_string(), KvsValue::I32(12345))]); |
| 1439 | + let result = factory.create(¶ms); |
| 1440 | + assert!(result.is_ok()); |
| 1441 | + } |
| 1442 | +} |
0 commit comments