diff --git a/src/instance.rs b/src/instance.rs index a19d41808530ff9c9018429bac21ebd88a819635..56b56c5c0a95d3e25f4812ff49ae35301dbcacd9 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -69,6 +69,8 @@ impl Instance { /// Index of first field is 0. pub const FIELD_FAILURE_DOMAIN: u32 = 7; + /// Format of the _pico_instance global table. + #[inline(always)] pub fn format() -> Vec<tarantool::space::Field> { use tarantool::space::{Field, FieldType}; vec![ diff --git a/src/replicaset.rs b/src/replicaset.rs index 2be5958629cf983e3664e6800c528d864b5face3..9d30ba62b6637586a43ef04ab70bb215931ee2b7 100644 --- a/src/replicaset.rs +++ b/src/replicaset.rs @@ -44,6 +44,8 @@ pub struct Replicaset { impl Encode for Replicaset {} impl Replicaset { + /// Format of the _pico_replicaset global table. + #[inline(always)] pub fn format() -> Vec<::tarantool::space::Field> { use ::tarantool::space::{Field, FieldType}; vec![ @@ -57,8 +59,9 @@ impl Replicaset { ] } + /// A dummy instance of the type for use in tests. #[inline(always)] - pub fn replicaset_for_tests() -> Self { + pub fn for_tests() -> Self { Self { replicaset_id: "r1".into(), replicaset_uuid: "r1-uuid".into(), @@ -122,7 +125,7 @@ mod tests { #[test] fn matches_format() { - let r = Replicaset::replicaset_for_tests(); + let r = Replicaset::for_tests(); let tuple_data = r.to_tuple_buffer().unwrap(); let format = Replicaset::format(); crate::util::check_tuple_matches_format(tuple_data.as_ref(), &format, "Replicaset::format"); diff --git a/src/schema.rs b/src/schema.rs index a90e1ad99dc3eafbaea9b37cdfaf2e883c4d1b5f..ee85d626c0147a351869734d289280640686c7b4 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -52,9 +52,40 @@ pub struct SpaceDef { impl Encode for SpaceDef {} impl SpaceDef { - // Don't forget to update this, if fields of `SpaceDef` change. + /// Index of field "operable" in the space _pico_space format. + /// + /// Index of first field is 0. pub const FIELD_OPERABLE: usize = 5; + /// Format of the _pico_space global table. + #[inline(always)] + pub fn format() -> Vec<tarantool::space::Field> { + use tarantool::space::Field; + vec![ + Field::from(("id", FieldType::Unsigned)), + Field::from(("name", FieldType::String)), + Field::from(("distribution", FieldType::Array)), + Field::from(("format", FieldType::Array)), + Field::from(("schema_version", FieldType::Unsigned)), + Field::from(("operable", FieldType::Boolean)), + Field::from(("engine", FieldType::String)), + ] + } + + /// A dummy instance of the type for use in tests. + #[inline(always)] + pub fn for_tests() -> Self { + Self { + id: 10569, + name: "stuff".into(), + distribution: Distribution::Global, + format: vec![], + schema_version: 420, + operable: true, + engine: SpaceEngineType::Blackhole, + } + } + pub fn to_space_metadata(&self) -> traft::Result<SpaceMetadata> { use tarantool::session::uid; @@ -158,9 +189,42 @@ pub struct IndexDef { impl Encode for IndexDef {} impl IndexDef { - // Don't forget to update this, if fields of `IndexDef` change. + /// Index of field "operable" in the space _pico_index format. + /// + /// Index of first field is 0. pub const FIELD_OPERABLE: usize = 6; + /// Format of the _pico_index global table. + #[inline(always)] + pub fn format() -> Vec<tarantool::space::Field> { + use tarantool::space::Field; + vec![ + Field::from(("space_id", FieldType::Unsigned)), + Field::from(("id", FieldType::Unsigned)), + Field::from(("name", FieldType::String)), + Field::from(("local", FieldType::Boolean)), + Field::from(("parts", FieldType::Array)), + Field::from(("schema_version", FieldType::Unsigned)), + Field::from(("operable", FieldType::Boolean)), + Field::from(("unique", FieldType::Boolean)), + ] + } + + /// A dummy instance of the type for use in tests. + #[inline(always)] + pub fn for_tests() -> Self { + Self { + space_id: 10569, + id: 1, + name: "secondary".into(), + local: true, + parts: vec![], + schema_version: 420, + operable: true, + unique: false, + } + } + pub fn to_index_metadata(&self) -> IndexMetadata { use tarantool::index::IndexType; @@ -195,7 +259,33 @@ pub struct UserDef { impl Encode for UserDef {} impl UserDef { + /// Index of field "auth" in the space _pico_user format. + /// + /// Index of first field is 0. pub const FIELD_AUTH: usize = 3; + + /// Format of the _pico_user global table. + #[inline(always)] + pub fn format() -> Vec<tarantool::space::Field> { + use tarantool::space::Field; + vec![ + Field::from(("id", FieldType::Unsigned)), + Field::from(("name", FieldType::String)), + Field::from(("schema_version", FieldType::Unsigned)), + Field::from(("auth", FieldType::Array)), + ] + } + + /// A dummy instance of the type for use in tests. + #[inline(always)] + pub fn for_tests() -> Self { + Self { + id: 69, + name: "david".into(), + schema_version: 421, + auth: AuthDef::new(tarantool::auth::AuthMethod::ChapSha1, "".into()), + } + } } //////////////////////////////////////////////////////////////////////////////// @@ -212,6 +302,29 @@ pub struct RoleDef { impl Encode for RoleDef {} +impl RoleDef { + /// Format of the _pico_role global table. + #[inline(always)] + pub fn format() -> Vec<tarantool::space::Field> { + use tarantool::space::Field; + vec![ + Field::from(("id", FieldType::Unsigned)), + Field::from(("name", FieldType::String)), + Field::from(("schema_version", FieldType::Unsigned)), + ] + } + + /// A dummy instance of the type for use in tests. + #[inline(always)] + pub fn for_tests() -> Self { + Self { + id: 13, + name: "devops".into(), + schema_version: 419, + } + } +} + //////////////////////////////////////////////////////////////////////////////// // PrivilegeDef //////////////////////////////////////////////////////////////////////////////// @@ -233,6 +346,35 @@ pub struct PrivilegeDef { impl Encode for PrivilegeDef {} +impl PrivilegeDef { + /// Format of the _pico_privilege global table. + #[inline(always)] + pub fn format() -> Vec<tarantool::space::Field> { + use tarantool::space::Field; + vec![ + Field::from(("grantor_id", FieldType::Unsigned)), + Field::from(("grantee_id", FieldType::Unsigned)), + Field::from(("object_type", FieldType::String)), + Field::from(("object_name", FieldType::String)), + Field::from(("privilege", FieldType::String)), + Field::from(("schema_version", FieldType::Unsigned)), + ] + } + + /// A dummy instance of the type for use in tests. + #[inline(always)] + pub fn for_tests() -> Self { + Self { + grantor_id: 13, + grantee_id: 37, + object_type: "fruit".into(), + object_name: "banana".into(), + privilege: "bite".into(), + schema_version: 337, + } + } +} + //////////////////////////////////////////////////////////////////////////////// // ... //////////////////////////////////////////////////////////////////////////////// @@ -909,3 +1051,60 @@ mod tests { assert_eq!(id, SPACE_ID_TEMPORARY_MIN); } } + +#[cfg(test)] +mod test { + use super::*; + use tarantool::tuple::ToTupleBuffer; + + #[test] + #[rustfmt::skip] + fn space_def_matches_format() { + let i = SpaceDef::for_tests(); + let tuple_data = i.to_tuple_buffer().unwrap(); + let format = SpaceDef::format(); + crate::util::check_tuple_matches_format(tuple_data.as_ref(), &format, "SpaceDef::format"); + + assert_eq!(format[SpaceDef::FIELD_OPERABLE as usize].name, "operable"); + } + + #[test] + #[rustfmt::skip] + fn index_def_matches_format() { + let i = IndexDef::for_tests(); + let tuple_data = i.to_tuple_buffer().unwrap(); + let format = IndexDef::format(); + crate::util::check_tuple_matches_format(tuple_data.as_ref(), &format, "IndexDef::format"); + + assert_eq!(format[IndexDef::FIELD_OPERABLE as usize].name, "operable"); + } + + #[test] + #[rustfmt::skip] + fn user_def_matches_format() { + let i = UserDef::for_tests(); + let tuple_data = i.to_tuple_buffer().unwrap(); + let format = UserDef::format(); + crate::util::check_tuple_matches_format(tuple_data.as_ref(), &format, "UserDef::format"); + + assert_eq!(format[UserDef::FIELD_AUTH as usize].name, "auth"); + } + + #[test] + #[rustfmt::skip] + fn role_def_matches_format() { + let i = RoleDef::for_tests(); + let tuple_data = i.to_tuple_buffer().unwrap(); + let format = RoleDef::format(); + crate::util::check_tuple_matches_format(tuple_data.as_ref(), &format, "RoleDef::format"); + } + + #[test] + #[rustfmt::skip] + fn privilege_def_matches_format() { + let i = PrivilegeDef::for_tests(); + let tuple_data = i.to_tuple_buffer().unwrap(); + let format = PrivilegeDef::format(); + crate::util::check_tuple_matches_format(tuple_data.as_ref(), &format, "PrivilegeDef::format"); + } +} diff --git a/src/storage.rs b/src/storage.rs index 6025f8db3b0abd5f7156e15882f373b160ce534a..aebbd42eb0733658c7c4cc465b889070701c9e6e 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1697,13 +1697,7 @@ impl Spaces { let space = Space::builder(Self::SPACE_NAME) .id(Self::SPACE_ID) .space_type(SpaceType::DataLocal) - .field(("id", FieldType::Unsigned)) - .field(("name", FieldType::String)) - .field(("distribution", FieldType::Array)) - .field(("format", FieldType::Array)) - .field(("schema_version", FieldType::Unsigned)) - .field(("operable", FieldType::Boolean)) - .field(("engine", FieldType::String)) + .format(SpaceDef::format()) .if_not_exists(true) .create()?; @@ -1784,14 +1778,7 @@ impl Indexes { let space = Space::builder(Self::SPACE_NAME) .id(Self::SPACE_ID) .space_type(SpaceType::DataLocal) - .field(("space_id", FieldType::Unsigned)) - .field(("id", FieldType::Unsigned)) - .field(("name", FieldType::String)) - .field(("local", FieldType::Boolean)) - .field(("parts", FieldType::Array)) - .field(("schema_version", FieldType::Unsigned)) - .field(("operable", FieldType::Boolean)) - .field(("unique", FieldType::Boolean)) + .format(IndexDef::format()) .if_not_exists(true) .create()?; @@ -2082,10 +2069,7 @@ impl Users { let space = Space::builder(Self::SPACE_NAME) .id(Self::SPACE_ID) .space_type(SpaceType::DataLocal) - .field(("id", FieldType::Unsigned)) - .field(("name", FieldType::String)) - .field(("schema_version", FieldType::Unsigned)) - .field(("auth", FieldType::Array)) + .format(UserDef::format()) .if_not_exists(true) .create()?; @@ -2175,9 +2159,7 @@ impl Roles { let space = Space::builder(Self::SPACE_NAME) .id(Self::SPACE_ID) .space_type(SpaceType::DataLocal) - .field(("id", FieldType::Unsigned)) - .field(("name", FieldType::String)) - .field(("schema_version", FieldType::Unsigned)) + .format(RoleDef::format()) .if_not_exists(true) .create()?; @@ -2259,12 +2241,7 @@ impl Privileges { let space = Space::builder(Self::SPACE_NAME) .id(Self::SPACE_ID) .space_type(SpaceType::DataLocal) - .field(("grantor_id", FieldType::Unsigned)) - .field(("grantee_id", FieldType::Unsigned)) - .field(("object_type", FieldType::String)) - .field(("object_name", FieldType::String)) - .field(("privilege", FieldType::String)) - .field(("schema_version", FieldType::Unsigned)) + .format(PrivilegeDef::format()) .if_not_exists(true) .create()?; @@ -2413,8 +2390,7 @@ impl Tiers { let space = Space::builder(Self::SPACE_NAME) .id(Self::SPACE_ID) .space_type(SpaceType::DataLocal) - .field(("name", FieldType::String)) - .field(("replication_factor", FieldType::Unsigned)) + .format(Tier::format()) .if_not_exists(true) .create()?; @@ -3165,7 +3141,7 @@ mod tests { storage.properties.space.insert(&("foo", "bar")).unwrap(); - let r = Replicaset::replicaset_for_tests(); + let r = Replicaset::for_tests(); storage.replicasets.space.insert(&r).unwrap(); let (snapshot_data, _) = storage @@ -3249,7 +3225,7 @@ mod tests { tuples, }); - let r = Replicaset::replicaset_for_tests(); + let r = Replicaset::for_tests(); let tuples = [&r].to_tuple_buffer().unwrap(); data.space_dumps.push(SpaceDump { space_id: ClusterwideSpace::Replicaset.into(), diff --git a/src/tier.rs b/src/tier.rs index 47135ed0b30203f1137b886f1f5a6531ba85f23c..8a03493b70958535ee4f59fa2f6a59fef7e6f1fb 100644 --- a/src/tier.rs +++ b/src/tier.rs @@ -10,23 +10,47 @@ pub struct Tier { pub name: String, pub replication_factor: u8, } +impl Encode for Tier {} -impl Default for Tier { - fn default() -> Self { +impl Tier { + /// Format of the _pico_tier global table. + #[inline(always)] + pub fn format() -> Vec<tarantool::space::Field> { + use tarantool::space::{Field, FieldType}; + vec![ + Field::from(("name", FieldType::String)), + Field::from(("replication_factor", FieldType::Unsigned)), + ] + } + + pub fn with_replication_factor(replication_factor: u8) -> Self { Tier { name: DEFAULT_TIER.into(), - replication_factor: 1, + replication_factor, } } } -impl Tier { - pub fn with_replication_factor(replication_factor: u8) -> Self { +impl Default for Tier { + fn default() -> Self { Tier { name: DEFAULT_TIER.into(), - replication_factor, + replication_factor: 1, } } } -impl Encode for Tier {} +#[cfg(test)] +mod tests { + use super::*; + use tarantool::tuple::ToTupleBuffer; + + #[test] + #[rustfmt::skip] + fn matches_format() { + let i = Tier::default(); + let tuple_data = i.to_tuple_buffer().unwrap(); + let format = Tier::format(); + crate::util::check_tuple_matches_format(tuple_data.as_ref(), &format, "Tier::format"); + } +}