mod common; use gitks::bare::GitBare; use gitks::error::GitError; use gitks::pb::RepositoryHeader; #[test] fn test_from_header_valid() { let (_dir, gb) = common::setup_bare_repo(); let parent = gb.bare_dir.parent().unwrap().to_string_lossy().into_owned(); let name = gb .bare_dir .file_name() .unwrap() .to_string_lossy() .into_owned(); let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: parent, relative_path: name, ..Default::default() }); assert!(result.is_ok()); } #[test] fn test_from_header_empty_path() { let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: String::new(), relative_path: String::new(), ..Default::default() }); assert!(result.is_err()); } #[test] fn test_from_header_relative_storage_path() { let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: "relative/path".into(), relative_path: String::new(), ..Default::default() }); assert!(result.is_err()); match result.unwrap_err() { GitError::InvalidArgument(_) => {} other => panic!("expected InvalidArgument, got: {:?}", other), } } #[test] fn test_from_header_relative_path_without_storage() { let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: String::new(), relative_path: "some/repo.git".into(), ..Default::default() }); assert!(result.is_err()); } #[test] fn test_from_header_nonexistent_repo() { let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: "/tmp".into(), relative_path: "nonexistent_repo_12345".into(), ..Default::default() }); assert!(result.is_err()); match result.unwrap_err() { GitError::RepoNotFound => {} other => panic!("expected RepoNotFound, got: {:?}", other), } } #[test] fn test_from_header_path_traversal() { let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: "/tmp".into(), relative_path: "../../../etc".into(), ..Default::default() }); assert!(result.is_err()); match result.unwrap_err() { GitError::InvalidArgument(msg) => { assert!( msg.contains("traversal"), "should detect traversal, got: {}", msg ); } other => panic!("expected InvalidArgument, got: {:?}", other), } } #[test] fn test_from_header_not_a_directory() { let dir = tempfile::tempdir().unwrap(); let file_path = dir.path().join("not_a_dir.txt"); std::fs::write(&file_path, "content").unwrap(); let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: dir.path().to_string_lossy().into_owned(), relative_path: "not_a_dir.txt".into(), ..Default::default() }); assert!(result.is_err()); } #[test] fn test_from_header_dir_without_head() { let dir = tempfile::tempdir().unwrap(); let subdir = dir.path().join("empty_dir"); std::fs::create_dir(&subdir).unwrap(); let result = GitBare::from_repository_header(&RepositoryHeader { storage_path: dir.path().to_string_lossy().into_owned(), relative_path: "empty_dir".into(), ..Default::default() }); assert!(result.is_err()); match result.unwrap_err() { GitError::NotBareRepository => {} other => panic!("expected NotBareRepository, got: {:?}", other), } } #[test] fn test_object_format() { let (_dir, gb) = common::setup_bare_repo(); let format = gb.object_format(); assert_eq!(format, gitks::pb::ObjectFormat::Sha1); } #[test] fn test_oid_to_pb() { let (_dir, gb) = common::setup_bare_repo(); let oid = gb.oid_to_pb("da39a3ee5e6b4b0d3255bfef95601890afd80709"); assert_eq!(oid.hex, "da39a3ee5e6b4b0d3255bfef95601890afd80709"); assert_eq!(oid.value.len(), 20); assert_eq!(oid.format, gitks::pb::ObjectFormat::Sha1 as i32); } #[test] fn test_oid_to_pb_invalid_hex() { let (_dir, gb) = common::setup_bare_repo(); let oid = gb.oid_to_pb("not_hex"); // Should return default (empty) bytes on invalid hex assert!(oid.value.is_empty()); assert_eq!(oid.hex, "not_hex"); }