1#[cfg(feature = "server")]
2use std::fs::File;
3#[cfg(feature = "server")]
4use std::io;
5#[cfg(feature = "server")]
6use std::io::BufRead;
7#[cfg(feature = "server")]
8use std::path::Path;
9
10#[cfg(feature = "fixtures-and-mocks")]
11use grovedb::TransactionArg;
12
13#[cfg(feature = "fixtures-and-mocks")]
14use crate::drive::Drive;
15#[cfg(feature = "fixtures-and-mocks")]
16use dpp::data_contract::DataContract;
17
18#[cfg(feature = "fixtures-and-mocks")]
19use dpp::block::block_info::BlockInfo;
20#[cfg(feature = "fixtures-and-mocks")]
21use dpp::prelude::Identifier;
22
23#[cfg(feature = "fixtures-and-mocks")]
24use crate::drive::votes::paths::vote_end_date_queries_tree_path_vec;
25#[cfg(feature = "fixtures-and-mocks")]
26use crate::query::VotePollsByEndDateDriveQuery;
27#[cfg(feature = "fixtures-and-mocks")]
28use crate::util::common::encode::decode_u64;
29#[cfg(feature = "fixtures-and-mocks")]
30use dpp::prelude::TimestampMillis;
31#[cfg(feature = "fixtures-and-mocks")]
32use dpp::tests::json_document::json_document_to_contract_with_ids;
33#[cfg(feature = "fixtures-and-mocks")]
34use dpp::version::PlatformVersion;
35#[cfg(feature = "fixtures-and-mocks")]
36use grovedb::query_result_type::QueryResultType;
37#[cfg(feature = "fixtures-and-mocks")]
38use grovedb::{PathQuery, Query};
39#[cfg(feature = "fixtures-and-mocks")]
40use std::collections::{BTreeMap, BTreeSet};
41
42#[cfg(feature = "fixtures-and-mocks")]
43use dpp::data_contract::schema::DataContractSchemaMethodsV0;
44#[cfg(feature = "fixtures-and-mocks")]
45use dpp::platform_value::Value as PlatformValue;
46
47#[cfg(test)]
48use ciborium::value::Value;
49
50#[cfg(test)]
51use crate::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo;
52#[cfg(test)]
53use crate::util::object_size_info::DocumentInfo::DocumentRefInfo;
54#[cfg(test)]
55use crate::util::object_size_info::{DataContractOwnedResolvedInfo, OwnedDocumentInfo};
56#[cfg(test)]
57use crate::util::storage_flags::StorageFlags;
58#[cfg(test)]
59use dpp::data_contract::accessors::v0::DataContractV0Getters;
60#[cfg(test)]
61use dpp::data_contract::document_type::random_document::{
62 CreateRandomDocument, DocumentFieldFillSize, DocumentFieldFillType,
63};
64#[cfg(test)]
65use dpp::document::DocumentV0Setters;
66#[cfg(test)]
67use dpp::platform_value;
68#[cfg(test)]
69use dpp::platform_value::Bytes32;
70#[cfg(test)]
71use dpp::voting::vote_info_storage::contested_document_vote_poll_stored_info::ContestedDocumentVotePollStoredInfo;
72#[cfg(test)]
73use rand::rngs::StdRng;
74#[cfg(test)]
75use rand::SeedableRng;
76
77#[cfg(any(test, feature = "server"))]
78pub mod setup;
79#[cfg(any(test, feature = "fixtures-and-mocks"))]
80pub mod test_utils;
82
83#[cfg(feature = "fixtures-and-mocks")]
84pub fn setup_contract(
86 drive: &Drive,
87 path: &str,
88 contract_id: Option<[u8; 32]>,
89 owner_id: Option<[u8; 32]>,
90 contract_modification: Option<impl FnOnce(&mut DataContract)>,
91 transaction: TransactionArg,
92 use_platform_version: Option<&PlatformVersion>,
93) -> DataContract {
94 let platform_version = use_platform_version.unwrap_or(PlatformVersion::latest());
95 let mut contract = json_document_to_contract_with_ids(
96 path,
97 contract_id.map(Identifier::from),
98 owner_id.map(Identifier::from),
99 false, platform_version,
101 )
102 .expect("expected to get json based contract");
103
104 if let Some(contract_modification) = contract_modification {
105 contract_modification(&mut contract);
106 }
107
108 drive
109 .apply_contract(
110 &contract,
111 BlockInfo::default(),
112 true,
113 None,
114 transaction,
115 platform_version,
116 )
117 .expect("contract should be applied");
118 contract
119}
120
121#[cfg(feature = "fixtures-and-mocks")]
122pub fn vote_poll_end_dates(
125 drive: &Drive,
126 platform_version: &PlatformVersion,
127) -> BTreeMap<TimestampMillis, BTreeSet<Identifier>> {
128 let mut query = Query::new();
129 query.insert_all();
130 let (end_dates, _) = drive
131 .grove_get_raw_path_query(
132 &PathQuery::new_unsized(vote_end_date_queries_tree_path_vec(), query),
133 None,
134 QueryResultType::QueryKeyElementPairResultType,
135 &mut vec![],
136 &platform_version.drive,
137 )
138 .expect("expected to read the end dates");
139 end_dates
140 .to_keys()
141 .into_iter()
142 .map(|end_date_key| {
143 let end_date = decode_u64(&end_date_key).expect("expected an encoded end date");
144 let unique_ids =
145 VotePollsByEndDateDriveQuery::execute_no_proof_keys_for_single_end_time(
146 end_date,
147 None,
148 drive,
149 None,
150 &mut vec![],
151 platform_version,
152 )
153 .expect("expected to read the vote polls of an end date")
154 .into_iter()
155 .map(|key| Identifier::from_bytes(&key).expect("expected a vote poll id"))
156 .collect();
157 (end_date, unique_ids)
158 })
159 .collect()
160}
161
162#[cfg(test)]
163pub(crate) fn dpns_name_contender_id(n: u64) -> Identifier {
166 let mut id = [0u8; 32];
167 id[..8].copy_from_slice(&(n + 1).to_be_bytes());
168 Identifier::from(id)
169}
170
171#[cfg(test)]
172pub(crate) fn add_dpns_name_contenders(
177 drive: &Drive,
178 dpns_contract: &DataContract,
179 label: &str,
180 contenders: std::ops::Range<u64>,
181 created_at: impl Fn(u64) -> TimestampMillis,
182 block_info: &BlockInfo,
183 platform_version: &PlatformVersion,
184) -> ContestedDocumentResourceVotePollWithContractInfo {
185 let document_type = dpns_contract
186 .document_type_for_name("domain")
187 .expect("expected the domain document type");
188 let vote_poll = ContestedDocumentResourceVotePollWithContractInfo {
189 contract: DataContractOwnedResolvedInfo::OwnedDataContract(dpns_contract.clone()),
190 document_type_name: "domain".to_string(),
191 index_name: "parentNameAndLabel".to_string(),
192 index_values: vec![
193 platform_value::Value::Text("dash".to_string()),
194 platform_value::Value::Text(label.to_string()),
195 ],
196 };
197 let mut rng = StdRng::seed_from_u64(contenders.start);
198 for n in contenders {
199 let owner_id = dpns_name_contender_id(n);
200 let mut document = document_type
201 .random_document_with_params(
202 owner_id,
203 Bytes32::random_with_rng(&mut rng),
204 Some(created_at(n)),
205 Some(block_info.height),
206 Some(block_info.core_height),
207 DocumentFieldFillType::FillIfNotRequired,
208 DocumentFieldFillSize::MinDocumentFillSize,
209 &mut rng,
210 platform_version,
211 )
212 .expect("expected a random domain");
213 document.set("parentDomainName", "dash".into());
214 document.set("normalizedParentDomainName", "dash".into());
215 document.set("label", label.into());
216 document.set("normalizedLabel", label.into());
217 document.set("records.identity", owner_id.into());
218 document.set("subdomainRules.allowSubdomains", false.into());
219 let stored_info = (n == 0).then(|| {
220 ContestedDocumentVotePollStoredInfo::new(*block_info, platform_version)
221 .expect("expected the poll's stored info")
222 });
223 drive
224 .add_contested_document(
225 OwnedDocumentInfo {
226 document_info: DocumentRefInfo((
227 &document,
228 StorageFlags::optional_default_as_cow(),
229 )),
230 owner_id: Some(owner_id.to_buffer()),
231 },
232 vote_poll.clone(),
233 false,
234 stored_info,
235 block_info,
236 true,
237 None,
238 platform_version,
239 )
240 .expect("expected to add the contender");
241 }
242 vote_poll
243}
244
245#[cfg(test)]
246pub fn cbor_from_hex(hex_string: String) -> Vec<u8> {
248 hex::decode(hex_string).expect("Decoding failed")
249}
250
251#[cfg(feature = "server")]
252pub fn text_file_strings(path: impl AsRef<Path>) -> Vec<String> {
254 let file = File::open(path).expect("file not found");
255 let reader = io::BufReader::new(file).lines();
256 reader.into_iter().map(|a| a.unwrap()).collect()
257}
258
259#[cfg(test)]
260pub fn get_key_from_cbor_map<'a>(
262 cbor_map: &'a [(Value, Value)],
263 key: &'a str,
264) -> Option<&'a Value> {
265 for (cbor_key, cbor_value) in cbor_map.iter() {
266 if !cbor_key.is_text() {
267 continue;
268 }
269
270 if cbor_key.as_text().expect("confirmed as text") == key {
271 return Some(cbor_value);
272 }
273 }
274 None
275}
276
277#[cfg(test)]
278pub fn cbor_inner_map_value<'a>(
280 document_type: &'a [(Value, Value)],
281 key: &'a str,
282) -> Option<&'a Vec<(Value, Value)>> {
283 let key_value = get_key_from_cbor_map(document_type, key)?;
284 if let Value::Map(map_value) = key_value {
285 return Some(map_value);
286 }
287 None
288}
289
290#[cfg(feature = "fixtures-and-mocks")]
291pub fn with_likes_read_whole_through_by_liker(
299 mut contract: DataContract,
300 platform_version: &PlatformVersion,
301) -> DataContract {
302 let mut schemas: BTreeMap<String, PlatformValue> = contract
303 .document_schemas()
304 .into_iter()
305 .map(|(name, schema)| (name, schema.clone()))
306 .collect();
307 let like = schemas.get_mut("like").expect("a like type");
308 {
309 let properties = like
310 .get_mut("properties")
311 .expect("like properties readable")
312 .expect("like properties");
313 properties.remove("hashtag").expect("a like hashtag");
314 let post_id = properties
315 .get_mut("postId")
316 .expect("like postId readable")
317 .expect("like postId");
318 post_id
319 .set_value("position", PlatformValue::U64(0))
320 .expect("postId position set");
321 post_id
322 .get_mut("refersTo")
323 .expect("postId refersTo readable")
324 .expect("postId refersTo")
325 .remove("where")
326 .expect("postId where");
327 }
328 like.get_mut("indices")
329 .expect("like indices readable")
330 .expect("like indices")
331 .as_array_mut()
332 .expect("like indices are an array")
333 .retain(|index| index.get_optional_str("name").ok().flatten() != Some("byHashtagPost"));
334 let defs = contract.schema_defs().cloned();
335 contract
336 .set_document_schemas(schemas, defs, true, &mut vec![], platform_version)
337 .expect("expected the like read whole through byLiker to parse");
338 contract
339}