1use rand::{rngs::StdRng, Rng, SeedableRng};
21use std::{env, error::Error, fs, io::Write, path::PathBuf};
22
23pub fn random_bytes(n: usize) -> Vec<u8> {
25 let mut result = vec![];
26 let mut rng = seedable_rng();
27 for _ in 0..n {
28 result.push(rng.gen_range(0..255));
29 }
30 result
31}
32
33pub fn seedable_rng() -> StdRng {
35 StdRng::seed_from_u64(42)
36}
37
38pub fn get_temp_file(file_name: &str, content: &[u8]) -> fs::File {
42 let mut path_buf = env::current_dir().unwrap();
44 path_buf.push("target");
45 path_buf.push("debug");
46 path_buf.push("testdata");
47 fs::create_dir_all(&path_buf).unwrap();
48 path_buf.push(file_name);
49
50 let mut tmp_file = fs::File::create(path_buf.as_path()).unwrap();
52 tmp_file.write_all(content).unwrap();
53 tmp_file.sync_all().unwrap();
54
55 let file = fs::OpenOptions::new()
57 .read(true)
58 .write(true)
59 .open(path_buf.as_path());
60 assert!(file.is_ok());
61 file.unwrap()
62}
63
64pub fn arrow_test_data() -> String {
79 match get_data_dir("ARROW_TEST_DATA", "../testing/data") {
80 Ok(pb) => pb.display().to_string(),
81 Err(err) => panic!("failed to get arrow data dir: {err}"),
82 }
83}
84
85pub fn parquet_test_data() -> String {
101 match get_data_dir("PARQUET_TEST_DATA", "../parquet-testing/data") {
102 Ok(pb) => pb.display().to_string(),
103 Err(err) => panic!("failed to get parquet data dir: {err}"),
104 }
105}
106
107fn get_data_dir(udf_env: &str, submodule_data: &str) -> Result<PathBuf, Box<dyn Error>> {
117 if let Ok(dir) = env::var(udf_env) {
119 let trimmed = dir.trim().to_string();
120 if !trimmed.is_empty() {
121 let pb = PathBuf::from(trimmed);
122 if pb.is_dir() {
123 return Ok(pb);
124 } else {
125 return Err(format!(
126 "the data dir `{}` defined by env {} not found",
127 pb.display(),
128 udf_env
129 )
130 .into());
131 }
132 }
133 }
134
135 let dir = env!("CARGO_MANIFEST_DIR");
141
142 let pb = PathBuf::from(dir).join(submodule_data);
143 if pb.is_dir() {
144 Ok(pb)
145 } else {
146 Err(format!(
147 "env `{}` is undefined or has empty value, and the pre-defined data dir `{}` not found\n\
148 HINT: try running `git submodule update --init`",
149 udf_env,
150 pb.display(),
151 ).into())
152 }
153}
154
155#[derive(Debug, Clone)]
157pub struct BadIterator<T> {
158 cur: usize,
160 limit: usize,
162 claimed: usize,
164 pub items: Vec<T>,
167}
168
169impl<T> BadIterator<T> {
170 pub fn new(limit: usize, claimed: usize, items: Vec<T>) -> Self {
173 assert!(!items.is_empty());
174 Self {
175 cur: 0,
176 limit,
177 claimed,
178 items,
179 }
180 }
181}
182
183impl<T: Clone> Iterator for BadIterator<T> {
184 type Item = T;
185
186 fn next(&mut self) -> Option<Self::Item> {
187 if self.cur < self.limit {
188 let next_item_idx = self.cur % self.items.len();
189 let next_item = self.items[next_item_idx].clone();
190 self.cur += 1;
191 Some(next_item)
192 } else {
193 None
194 }
195 }
196
197 fn size_hint(&self) -> (usize, Option<usize>) {
199 (0, Some(self.claimed))
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206
207 #[test]
208 fn test_data_dir() {
209 let udf_env = "get_data_dir";
210 let cwd = env::current_dir().unwrap();
211
212 let existing_pb = cwd.join("..");
213 let existing = existing_pb.display().to_string();
214 let existing_str = existing.as_str();
215
216 let non_existing = cwd.join("non-existing-dir").display().to_string();
217 let non_existing_str = non_existing.as_str();
218
219 env::set_var(udf_env, non_existing_str);
220 let res = get_data_dir(udf_env, existing_str);
221 assert!(res.is_err());
222
223 env::set_var(udf_env, "");
224 let res = get_data_dir(udf_env, existing_str);
225 assert!(res.is_ok());
226 assert_eq!(res.unwrap(), existing_pb);
227
228 env::set_var(udf_env, " ");
229 let res = get_data_dir(udf_env, existing_str);
230 assert!(res.is_ok());
231 assert_eq!(res.unwrap(), existing_pb);
232
233 env::set_var(udf_env, existing_str);
234 let res = get_data_dir(udf_env, existing_str);
235 assert!(res.is_ok());
236 assert_eq!(res.unwrap(), existing_pb);
237
238 env::remove_var(udf_env);
239 let res = get_data_dir(udf_env, non_existing_str);
240 assert!(res.is_err());
241
242 let res = get_data_dir(udf_env, existing_str);
243 assert!(res.is_ok());
244 assert_eq!(res.unwrap(), existing_pb);
245 }
246
247 #[test]
248 fn test_happy() {
249 let res = arrow_test_data();
250 assert!(PathBuf::from(res).is_dir());
251
252 let res = parquet_test_data();
253 assert!(PathBuf::from(res).is_dir());
254 }
255}