Skip to main content

drive/util/test_helpers/
setup.rs

1//! Drive Setup Helpers.
2//!
3//! Defines helper functions pertinent to setting up Drive.
4//!
5
6#[cfg(feature = "full")]
7use crate::config::DriveConfig;
8use crate::drive::Drive;
9use dpp::block::block_info::BlockInfo;
10
11use crate::util::object_size_info::DocumentInfo::DocumentRefInfo;
12use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo};
13use dpp::data_contract::document_type::DocumentTypeRef;
14use dpp::data_contract::DataContract;
15use dpp::document::Document;
16
17use dpp::version::PlatformVersion;
18use grovedb::TransactionArg;
19#[cfg(feature = "full")]
20use tempfile::TempDir;
21
22/// Struct with options regarding setting up fee pools.
23pub struct SetupFeePoolsOptions {
24    /// Bool indicating whether the fee pool structure should be applied upon setup.
25    pub apply_fee_pool_structure: bool,
26}
27
28impl Default for SetupFeePoolsOptions {
29    /// The default is true for applying the fee pool structure upon setting up fee pools.
30    fn default() -> SetupFeePoolsOptions {
31        SetupFeePoolsOptions {
32            apply_fee_pool_structure: true,
33        }
34    }
35}
36
37#[cfg(feature = "full")]
38/// Sets up Drive using a temporary directory and the optionally given Drive configuration settings.
39///
40/// The returned Drive owns the directory, which is removed when the Drive is dropped.
41pub fn setup_drive(drive_config: Option<DriveConfig>) -> Drive {
42    let tmp_dir = TempDir::new().unwrap();
43
44    let (mut drive, _) =
45        Drive::open(tmp_dir.path(), drive_config).expect("should open Drive successfully");
46    drive.temp_dir = Some(tmp_dir);
47
48    drive
49}
50
51#[cfg(feature = "full")]
52/// Sets up Drive using a temporary directory and the default initial state structure.
53pub fn setup_drive_with_initial_state_structure(
54    specific_platform_version: Option<&PlatformVersion>,
55) -> Drive {
56    let drive = setup_drive(Some(DriveConfig {
57        batching_consistency_verification: true,
58        ..Default::default()
59    }));
60
61    let platform_version = specific_platform_version.unwrap_or(PlatformVersion::latest());
62    drive
63        .create_initial_state_structure(None, platform_version)
64        .expect("should create root tree successfully");
65
66    drive
67}
68
69/// A function to setup system data contract
70pub fn setup_system_data_contract(
71    drive: &Drive,
72    data_contract: &DataContract,
73    transaction: TransactionArg,
74) {
75    let platform_version = PlatformVersion::latest();
76    drive
77        .apply_contract(
78            data_contract,
79            BlockInfo::default(),
80            true,
81            None,
82            transaction,
83            platform_version,
84        )
85        .unwrap();
86}
87
88/// Setup document for a contract
89pub fn setup_document(
90    drive: &Drive,
91    document: &Document,
92    data_contract: &DataContract,
93    document_type: DocumentTypeRef,
94    transaction: TransactionArg,
95) {
96    let platform_version = PlatformVersion::latest();
97    drive
98        .add_document_for_contract(
99            DocumentAndContractInfo {
100                owned_document_info: OwnedDocumentInfo {
101                    document_info: DocumentRefInfo((document, None)),
102                    owner_id: None,
103                },
104                contract: data_contract,
105                document_type,
106            },
107            false,
108            BlockInfo::default(),
109            true,
110            transaction,
111            platform_version,
112            None,
113        )
114        .unwrap();
115}
116
117#[cfg(all(test, feature = "full"))]
118mod tests {
119    use super::*;
120    use crate::drive::system::misc_path;
121    use grovedb::Element;
122
123    #[test]
124    fn should_write_new_database_files_after_setup_returns() {
125        let drive = setup_drive_with_initial_state_structure(None);
126        let grove_version = &PlatformVersion::latest().drive.grove_version;
127        let item = Element::new_item(vec![7; 1024]);
128
129        drive
130            .grove
131            .insert(
132                &misc_path(),
133                b"after setup",
134                item.clone(),
135                None,
136                None,
137                grove_version,
138            )
139            .unwrap()
140            .expect("should insert an item");
141
142        // A flush starts a new log file and writes the memtable to a new table file, both
143        // created in the Drive's directory, so it fails once that directory is gone.
144        drive
145            .grove
146            .flush()
147            .expect("should flush the memtable to disk");
148
149        let stored = drive
150            .grove
151            .get(&misc_path(), b"after setup", None, grove_version)
152            .unwrap()
153            .expect("should read the item back");
154        assert_eq!(stored, item);
155    }
156
157    #[test]
158    fn should_remove_the_temp_directory_when_the_drive_is_dropped() {
159        let drive = setup_drive(None);
160        let path = drive
161            .temp_dir
162            .as_ref()
163            .expect("setup_drive should hand its temporary directory to the Drive")
164            .path()
165            .to_path_buf();
166        assert!(path.exists());
167
168        drop(drive);
169
170        assert!(!path.exists());
171    }
172}