From 92a76613e5ebd1e3250512aeebb5c083fcc43d13 Mon Sep 17 00:00:00 2001
From: peterrabbit <pierre.jarriges@tutanota.com>
Date: Sun, 4 Sep 2022 17:35:13 +0200
Subject: [PATCH] test static files manager

---
 src/static_files.rs | 184 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 168 insertions(+), 16 deletions(-)

diff --git a/src/static_files.rs b/src/static_files.rs
index a8364f2..0f07ddd 100644
--- a/src/static_files.rs
+++ b/src/static_files.rs
@@ -7,6 +7,15 @@ pub struct StaticFilesManager {
     pub index: Vec<String>,
 }
 
+const STATIC_ASSETS_DIRECTORIES: [&'static str; 6] = [
+    "images",
+    "sounds",
+    "videos",
+    "docs",
+    "source_code",
+    "default",
+];
+
 impl StaticFilesManager {
     pub fn new(app_state: &AppState) -> Result<Self, String> {
         match Self::create_dir_if_missing(&app_state.config.storage_dir) {
@@ -18,12 +27,27 @@ impl StaticFilesManager {
         }
     }
 
+    #[cfg(test)]
+    pub fn testing_new(test_dir: &PathBuf) -> Result<Self, String> {
+        match Self::create_dir_if_missing(test_dir) {
+            Ok(dir) => Ok(StaticFilesManager {
+                index: Vec::new(),
+                dir,
+            }),
+            Err(msg) => Err(msg),
+        }
+    }
+
     fn create_dir_if_missing(app_dir: &PathBuf) -> Result<PathBuf, String> {
         let static_dir = app_dir.join("static");
 
         if !static_dir.exists() {
             match std::fs::create_dir_all(&static_dir) {
                 Ok(_) => {
+                    if let Err(err) = Self::create_assets_directories_structure(&static_dir) {
+                        return Err(format!("{}", err));
+                    };
+
                     if let Err(err) = Self::copy_default_files(&static_dir) {
                         return Err(format!("{}", err));
                     }
@@ -35,19 +59,22 @@ impl StaticFilesManager {
         Ok(static_dir)
     }
 
+    fn create_assets_directories_structure(root: &PathBuf) -> Result<(), std::io::Error> {
+        for d in STATIC_ASSETS_DIRECTORIES {
+            std::fs::create_dir(root.join(d))?;
+        }
+
+        Ok(())
+    }
+
     fn copy_default_files(static_dir: &PathBuf) -> Result<(), String> {
         let local_default_static = std::env::current_dir().unwrap().join("default_static");
         let default_static = static_dir.join("default");
-        match std::fs::create_dir_all(&default_static) {
+        let mut cpy_options = fs_extra::dir::CopyOptions::new();
+        cpy_options.content_only = true;
+        match fs_extra::dir::copy(local_default_static, default_static, &cpy_options) {
             Err(err) => Err(format!("{}", err)),
-            Ok(_) => {
-                let mut cpy_options = fs_extra::dir::CopyOptions::new();
-                cpy_options.content_only = true;
-                match fs_extra::dir::copy(local_default_static, default_static, &cpy_options) {
-                    Err(err) => Err(format!("{}", err)),
-                    Ok(_) => Ok(()),
-                }
-            }
+            Ok(_) => Ok(()),
         }
     }
 
@@ -57,20 +84,44 @@ impl StaticFilesManager {
                 if entry.path().is_dir() {
                     self.rec_read_dir(&entry.path(), strip_from);
                 } else {
-                    self._push_path(&entry.path(), strip_from);
+                    self.push_path(&entry.path().strip_prefix(strip_from).unwrap());
                 }
             }
         }
     }
 
-    fn _push_path(&mut self, path: &Path, strip_from: &Path) {
-        let push_path = path.strip_prefix(strip_from).unwrap();
-        self.index
-            .push(format!("/{}", push_path.to_str().unwrap().to_owned()));
+    fn validate_path(&self, path: &Path) -> bool {
+        self.dir.join(self.clean_relative_path(path)).exists()
+    }
+
+    fn clean_relative_path(&self, path: &Path) -> PathBuf {
+        match path.starts_with("/") {
+            true => path.strip_prefix("/").unwrap().to_path_buf(),
+            false => path.to_path_buf(),
+        }
+    }
+
+    fn push_path(&mut self, path: &Path) -> Vec<PathBuf> {
+        if self.validate_path(path) {
+            self.index
+                .push(format!("/{}", path.to_str().unwrap().to_owned()));
+            vec![path.to_path_buf()]
+        } else {
+            println!(
+                "[WARNING] Error building static file index. The file {:?} doesn't exist and will be removed from the index.",
+                self.dir.join(self.clean_relative_path(path)),
+            );
+            Vec::new()
+        }
     }
 
-    pub fn add_pathes(&mut self, pathes: &Vec<String>) {
-        self.index.extend(pathes.iter().map(|p| p.to_owned()));
+    pub fn add_pathes(&mut self, pathes: &Vec<String>) -> Vec<PathBuf> {
+        let mut added: Vec<PathBuf> = Vec::new();
+        for pth in pathes.iter() {
+            let p = self.push_path(Path::new(pth));
+            added.extend(p.iter().map(|pb| pb.clone()));
+        }
+        added
     }
 
     pub fn build(&mut self) -> Self {
@@ -79,3 +130,104 @@ impl StaticFilesManager {
         self.clone()
     }
 }
+
+#[cfg(test)]
+mod test_static_files_manager {
+    use super::*;
+
+    fn create_test_dir() -> PathBuf {
+        let pth = PathBuf::from("./test");
+        let _ = std::fs::create_dir(&pth);
+        pth
+    }
+
+    fn remove_test_dir(pth: &PathBuf) {
+        let _ = std::fs::remove_dir_all(pth);
+    }
+
+    #[test]
+    fn test_directory_structure() {
+        let test_dir = create_test_dir();
+        let _manager = StaticFilesManager::testing_new(&test_dir).unwrap();
+
+        for d in STATIC_ASSETS_DIRECTORIES {
+            let p = test_dir.join("static").join(d);
+            let exists = p.exists();
+            assert!(
+                exists,
+                "{} doesn't exist\n{:?}",
+                p.display(),
+                remove_test_dir(&test_dir)
+            );
+        }
+
+        remove_test_dir(&test_dir);
+    }
+
+    #[test]
+    fn test_indexation() {
+        let test_dir = create_test_dir();
+        let mut manager = StaticFilesManager::testing_new(&test_dir).unwrap();
+        let file_pth = test_dir.join("static").join("docs").join("testing.txt");
+        std::fs::File::create(&file_pth).unwrap();
+        manager = manager.build();
+
+        assert!(
+            manager.index.contains(&"/docs/testing.txt".to_string()),
+            "Index doesn't contain path /docs/testing.txt\n{:?}",
+            remove_test_dir(&test_dir)
+        );
+
+        remove_test_dir(&test_dir);
+    }
+
+    #[test]
+    fn test_push_path() {
+        let test_dir = create_test_dir();
+        let mut manager = StaticFilesManager::testing_new(&test_dir).unwrap().build();
+        let file_pth = test_dir.join("static").join("docs").join("testing.txt");
+        std::fs::File::create(&file_pth).unwrap();
+        let indexed_path = Path::new("docs/testing.txt");
+        let added = manager.push_path(&indexed_path);
+
+        assert_eq!(
+            added,
+            vec![PathBuf::from("docs/testing.txt")],
+            "Path was not added\n{:?}",
+            remove_test_dir(&test_dir)
+        );
+
+        assert!(
+            manager.index.contains(&"/docs/testing.txt".to_string()),
+            "Index doesn't contain path /docs/testing.txt\n{:?}",
+            remove_test_dir(&test_dir)
+        );
+
+        remove_test_dir(&test_dir);
+    }
+
+    #[test]
+    fn test_push_unexisting_path() {
+        let test_dir = create_test_dir();
+        let mut manager = StaticFilesManager::testing_new(&test_dir).unwrap().build();
+        let indexed_path = Path::new("images/unexisting.png");
+        let added = manager.push_path(&indexed_path);
+
+        assert_eq!(
+            added.len(),
+            0,
+            "No path should have been added\n{:?}",
+            remove_test_dir(&test_dir)
+        );
+
+        assert!(
+            !manager
+                .index
+                .contains(&"/images/unexisting.png".to_string()),
+            "Index shouldn't container unexisting path\n{:?}",
+            remove_test_dir(&test_dir)
+        );
+
+        remove_test_dir(&test_dir);
+    }
+}
-- 
GitLab