Skip to content

Commit

Permalink
Add unit test for serveral mod (#7)
Browse files Browse the repository at this point in the history
* feat: add unit test

* CodeCov test

* Update README.md

* feat: Add Makefile
  • Loading branch information
MissterHao authored Nov 25, 2022
1 parent 9e70013 commit fd09721
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 34 deletions.
28 changes: 28 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This is a makefile just for maintainer who is using windows operation system as developing environment.

.PHONY: all
all:
set RUSTFLAGS=
set LLVM_PROFILE_FILE=
cargo run

.PHONY: lint
lint:
set RUSTFLAGS=
set LLVM_PROFILE_FILE=
cargo fmt --check -- --color always
cargo clippy --all-targets -- -D warnings

.PHONY: clean
clean:
del *.profraw

.PHONY: test
test:
set LLVM_PROFILE_FILE=ruscode-%p-%m.profraw
set "RUSTFLAGS=-Cinstrument-coverage -Ccodegen-units=1 -Clink-dead-code -Coverflow-checks=on"
cargo build
cargo test
set
grcov . --binary-path ./target/debug/ -s . -t html --branch --ignore-not-existing -o ./coverage/

23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,26 @@
<img
src="https://img.shields.io/github/issues/MissterHao/ruscode?style=for-the-badge" alt="Github Issue badge" />
</a>
<a href="https://github.com/MissterHao/ruscode" style="margin-right: 8px;">
<a href="https://github.com/MissterHao/ruscode/actions/workflows/release.yml" style="margin-right: 8px;">
<img
src="https://img.shields.io/github/license/MissterHao/ruscode?style=for-the-badge" alt="Lience badge" />
src="https://img.shields.io/github/workflow/status/MissterHao/ruscode/release?style=for-the-badge" alt="Github Release Action status badge" />
</a>
<a href="https://github.com/MissterHao/ruscode" style="margin-right: 8px;">
<a href="https://codecov.io/gh/MissterHao/ruscode" style="margin-right: 8px;">
<img
src="https://img.shields.io/codecov/c/gh/MissterHao/ruscode?style=for-the-badge&token=8TU7FS0R56" alt="codecov" >
</a>
<a href="https://github.com/MissterHao/ruscode">
<img
src="https://img.shields.io/badge/Language-Rust-%23EB6400?style=for-the-badge&logo=Rust" alt="Rust badge" >
</a>
<br>
<a href="https://github.com/MissterHao/ruscode" style="margin-right: 8px;">
<img
src="https://img.shields.io/github/downloads/MissterHao/ruscode/total?style=for-the-badge&logo=Rust" alt="Rust badge" >
src="https://img.shields.io/github/license/MissterHao/ruscode?style=for-the-badge" alt="Lience badge" />
</a>
<br>
<a href="https://codecov.io/gh/MissterHao/ruscode">
<a href="https://github.com/MissterHao/ruscode" style="margin-right: 8px;">
<img
src="https://img.shields.io/codecov/c/gh/MissterHao/ruscode?style=for-the-badge&token=8TU7FS0R56" alt="codecov" >
src="https://img.shields.io/github/downloads/MissterHao/ruscode/total?style=for-the-badge&logo=Rust" alt="Rust badge" >
</a>

<br>
Expand All @@ -42,6 +46,11 @@
<img
src="https://img.shields.io/badge/MacOS%20Version-Latest-blue?style=for-the-badge&logo=macOS" alt="macOS supported badge" >
</a>
<br>
<a href="https://codecov.io/gh/mozilla/grcov">
<img
src="https://codecov.io/gh/MissterHao/ruscode/branch/unit-test/graph/badge.svg" alt="codecov" >
</a>
</p>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/application/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl<'a> App<'a> {
/// Init environment
pub fn init_environment(&mut self) -> Result<(), ApplicationError> {
// Default app folder create
init_application_folders().expect("Failed to create application folders.");
init_application_folders(None).expect("Failed to create application folders.");

// Make sure database is always exists
self.create_database(SystemPaths::database().as_str())
Expand Down
110 changes: 100 additions & 10 deletions src/common/system.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
use crate::common::text::strip_trailing_newline;
use std::process::Command;
use std::process::{Command, Output};
use std::str;

pub struct SystemPaths {}

impl SystemPaths {
fn windows_user_home_dir() -> Output {
Command::new("cmd")
.args(["/C", "echo %userprofile%"])
.output()
.expect("failed to execute process")
}

fn ubuntu_user_home_dir() -> Output {
Command::new("sh")
.arg("-c")
.arg("getent passwd \"$USER\" | cut -d: -f6 ")
.output()
.expect("failed to execute process")
}

pub fn home_dir() -> String {
let output = if cfg!(target_os = "windows") {
Command::new("cmd")
.args(["/C", "echo %userprofile%"])
.output()
.expect("failed to execute process")
SystemPaths::windows_user_home_dir()
} else {
Command::new("sh")
.arg("-c")
.arg("getent passwd \"$USER\" | cut -d: -f6 ")
.output()
.expect("failed to execute process")
SystemPaths::ubuntu_user_home_dir()
};

let home = strip_trailing_newline(str::from_utf8(&output.stdout).unwrap());
Expand Down Expand Up @@ -75,4 +83,86 @@ mod test_system {
fn test_systempaths_homedir_should_work_without_panic() {
assert_eq!(type_of(SystemPaths::home_dir()), type_of(String::new()));
}

#[cfg(target_os = "windows")]
#[test]
fn test_systempaths_on_windows() {
SystemPaths::windows_user_home_dir();
}
#[cfg(target_os = "windows")]
#[test]
fn test_systempaths_on_windows_re_format() {
let output = SystemPaths::windows_user_home_dir();
let path = str::from_utf8(&output.stdout).unwrap();
let re = regex::Regex::new(r".*\\Users\\.*").unwrap();
assert!(re.is_match(path));
}

#[cfg(target_os = "linux")]
#[test]
fn test_systempaths_on_linux() {
SystemPaths::ubuntu_user_home_dir();
}
#[cfg(target_os = "linux")]
#[test]
fn test_systempaths_on_linux_re_format() {
let output = SystemPaths::ubuntu_user_home_dir();
let path = str::from_utf8(&output.stdout).unwrap();
let re = regex::Regex::new(r"/home/.*").unwrap();
assert!(re.is_match(path));
}

#[test]
fn test_systempaths_get_home_dir() {
let home_dir = SystemPaths::home_dir();
assert_eq!(type_of(&home_dir), type_of(&String::new()));

let re = regex::Regex::new(r"\\\\").unwrap();
assert_eq!(re.find_iter(home_dir.as_str()).count(), 0);
}

#[cfg(target_os = "windows")]
#[test]
fn test_vscode_workspace_storage_path_on_windows() {
let path = SystemPaths::vscode_workspace_storage_path();
let re =
regex::Regex::new(".*/AppData/Roaming/Code/User/workspaceStorage/.*/workspace.json")
.unwrap();

assert!(re.is_match(path.as_str()));
}
#[cfg(target_os = "linux")]
#[test]
#[should_panic]
fn test_vscode_workspace_storage_path_on_linux() {
SystemPaths::vscode_workspace_storage_path();
}

#[cfg(target_os = "windows")]
#[test]
fn test_application_data_folder_path_on_windows() {
let path = SystemPaths::application_data_folder();
let re = regex::Regex::new(".*/AppData/Local/ruscode").unwrap();
assert!(re.is_match(path.as_str()));
}

#[cfg(target_os = "linux")]
#[test]
fn test_application_data_folder_path_on_linux() {
let path = SystemPaths::application_data_folder();
let re = regex::Regex::new("/var/lib/ruscode").unwrap();
assert!(re.is_match(path.as_str()));
}

#[test]
fn test_database_folder() {
let path = SystemPaths::application_data_folder();
assert_eq!(format!("{}/database", path), SystemPaths::database_folder());
}

#[test]
fn test_database_file_path() {
let path = SystemPaths::database_folder();
assert_eq!(format!("{}/data.db", path), SystemPaths::database());
}
}
20 changes: 20 additions & 0 deletions src/common/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,23 @@ pub fn strip_trailing_newline(input: &str) -> &str {
.or_else(|| input.strip_suffix('\n'))
.unwrap_or(input)
}

#[cfg(test)]
mod test_text {
use super::strip_trailing_newline;

#[test]
fn strref_should_strip_newline() {
let input = "This is a sentence with newline\r\n";
let input2 = "This is a sentence with newline\n";

assert_eq!(
strip_trailing_newline(input),
"This is a sentence with newline"
);
assert_eq!(
strip_trailing_newline(input2),
"This is a sentence with newline"
);
}
}
24 changes: 24 additions & 0 deletions src/domain/entity/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,27 @@ impl Tag {
}
}
}

#[cfg(test)]
mod test_tag_entity {
use super::Tag;

#[test]
fn tag_entity_should_create_successfully_with_new_associate_function() {
assert_eq!(Tag::new().name, String::from(""));
}

#[test]
fn tag_entity_should_create_successfully_with_init() {
let t = Tag {
name: String::new(),
};
assert_eq!(t.name, String::new());
}

#[test]
fn tag_entity_should_print_successfully_in_debug_mode() {
let t = Tag::new();
format!("{:?}", t);
}
}
10 changes: 0 additions & 10 deletions src/domain/system/folder_observer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,5 @@ mod test_folder_observer {
fn test_last_modified() {
// let sys_time = last_modified();
// let last_modified_secs = sys_time.duration_since(UNIX_EPOCH).unwrap().as_secs();

// println!(
// "{:?}",
// Utc.timestamp_opt(last_modified_secs as i64, 0)
// .unwrap()
// .format("%Y/%m/%d")
// .to_string()
// );

// println!("{:?}", last_modified_secs);
}
}
32 changes: 28 additions & 4 deletions src/domain/system/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,33 @@ use std::fs;
use super::error::ApplicationInitError;
use crate::common::system::SystemPaths;

pub fn init_application_folders() -> Result<(), ApplicationInitError> {
let database_path = SystemPaths::database_folder();
fs::create_dir_all(database_path).expect("Cannot create application folders.");

pub fn init_application_folders(path: Option<String>) -> Result<(), ApplicationInitError> {
let create_path: String = match path {
Some(val) => val,
None => SystemPaths::database_folder(),
};
fs::create_dir_all(create_path).expect("Cannot create application folders.");
Ok(())
}

#[cfg(test)]
mod test_system_init {
use std::fs;

use super::init_application_folders;

#[test]
fn test_fake_application_folder_creation() {
let fake_dir_path = "fake/dir/folder";
let fake_dir_path_root = "fake";

match init_application_folders(Some(String::from(fake_dir_path))) {
Ok(_) => {
fs::remove_dir_all(fake_dir_path_root).expect("Remove fake dirs failed.");
}
Err(_) => {
panic!("Cannot create fake application folder.");
}
};
}
}
10 changes: 9 additions & 1 deletion src/domain/value_object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ mod test_workspacejson {
};
assert_eq!(_w.folder, String::from("folder"));
}

#[test]
fn test_workspacejson_string_debug_format() {
format!(
"{:?}",
WorkspaceJson {
folder: String::from("")
}
);
}
#[test]
fn test_workspacejson_is_deserializeable() {
let _w = WorkspaceJson {
Expand Down
28 changes: 28 additions & 0 deletions src/infrastructure/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,31 @@ pub fn get_db_connection(path: &str) -> Result<Connection, DatabaseError> {

Ok(db_connection)
}

#[cfg(test)]
mod test_database {
use std::fs;

use super::{create_database, get_db_connection};

#[test]
fn test_database_should_create_succesfully() {
let testing_database_path = "./test-database.sqlite3";
if create_database(testing_database_path).is_ok() {
fs::remove_file(testing_database_path).unwrap();
} else {
panic!("Database create failed!")
}
}

#[test]
fn test_database_connection_should_succesfully() {
let testing_database_path = "./test-database-conn.sqlite3";
if create_database(testing_database_path).is_ok() {
get_db_connection(testing_database_path).expect("Cannot get database connection!");
fs::remove_file(testing_database_path).unwrap();
} else {
panic!("Database create failed!")
}
}
}
1 change: 0 additions & 1 deletion src/infrastructure/repository/workspace_repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ impl WorkspaceRepository {
let db_connection = get_db_connection(SystemPaths::database().as_str())
.expect("Cannot get database connection.");

println!("{sql}");
let mut stmt = db_connection
.prepare(&sql)
.expect("Failed to select all workspaces.");
Expand Down

0 comments on commit fd09721

Please sign in to comment.