uconsole_sleep/hardware/
framebuffer.rs1use crate::error::Error;
4use std::path::PathBuf;
5
6#[cfg(test)]
7use std::fs;
8
9const FRAMEBUFFER_PATH: &str = "/sys/class/graphics/fb0";
10
11pub fn find_framebuffer() -> Result<Option<PathBuf>, Error> {
18 let path = PathBuf::from(FRAMEBUFFER_PATH);
19
20 match path.try_exists() {
21 Ok(exists) => {
22 if exists {
23 Ok(Some(path))
24 } else {
25 Ok(None)
26 }
27 }
28 Err(e) => Err(Error::from(e)),
29 }
30}
31
32#[cfg(test)]
42fn get_virtual_resolution(path: &std::path::Path) -> Result<Option<(u32, u32)>, Error> {
43 let virtual_size_path = path.join("virtual_size");
44
45 match fs::read_to_string(&virtual_size_path) {
46 Ok(content) => {
47 let parts: Vec<&str> = content.trim().split(',').collect();
48 if let (Ok(width), Ok(height)) = (
49 parts[0].trim().parse::<u32>(),
50 parts[1].trim().parse::<u32>(),
51 ) && parts.len() == 2
52 {
53 return Ok(Some((width, height)));
54 }
55 Ok(None)
56 }
57 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
58 Err(e) => Err(Error::from(e)),
59 }
60}
61
62#[cfg(test)]
72fn get_physical_resolution(path: &std::path::Path) -> Result<Option<(u32, u32)>, Error> {
73 let phys_size_path = path.join("phys_size");
74
75 match fs::read_to_string(&phys_size_path) {
76 Ok(content) => {
77 let parts: Vec<&str> = content.trim().split(',').collect();
78 if let (Ok(width), Ok(height)) = (
79 parts[0].trim().parse::<u32>(),
80 parts[1].trim().parse::<u32>(),
81 ) && parts.len() == 2
82 {
83 return Ok(Some((width, height)));
84 }
85 Ok(None)
86 }
87 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
88 Err(e) => Err(Error::from(e)),
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_framebuffer_path_constant() {
98 assert_eq!(FRAMEBUFFER_PATH, "/sys/class/graphics/fb0");
99 }
100
101 #[test]
102 fn test_find_framebuffer_returns_option() {
103 if find_framebuffer().is_ok() {}
104 }
105
106 #[test]
107 fn test_virtual_resolution_parsing_valid() {
108 let virtual_size_str = "1920,1080";
109 let parts: Vec<&str> = virtual_size_str.trim().split(',').collect();
110 assert_eq!(parts.len(), 2);
111 assert_eq!(parts[0].trim().parse::<u32>().unwrap(), 1920);
112 assert_eq!(parts[1].trim().parse::<u32>().unwrap(), 1080);
113 }
114
115 #[test]
116 fn test_physical_resolution_parsing_valid() {
117 let phys_size_str = "268,150";
118 let parts: Vec<&str> = phys_size_str.trim().split(',').collect();
119 assert_eq!(parts.len(), 2);
120 assert_eq!(parts[0].trim().parse::<u32>().unwrap(), 268);
121 assert_eq!(parts[1].trim().parse::<u32>().unwrap(), 150);
122 }
123
124 #[test]
125 fn test_resolution_parsing_with_whitespace() {
126 let size_str = " 1920 , 1080 ";
127 let parts: Vec<&str> = size_str.trim().split(',').collect();
128 assert_eq!(parts[0].trim().parse::<u32>().unwrap(), 1920);
129 assert_eq!(parts[1].trim().parse::<u32>().unwrap(), 1080);
130 }
131
132 #[test]
133 fn test_resolution_parsing_various_sizes() {
134 let sizes = vec![
135 ("640,480", (640, 480)),
136 ("1024,768", (1024, 768)),
137 ("1920,1080", (1920, 1080)),
138 ];
139
140 for (size_str, (expected_width, expected_height)) in sizes {
141 let parts: Vec<&str> = size_str.split(',').collect();
142 let width = parts[0].trim().parse::<u32>().unwrap();
143 let height = parts[1].trim().parse::<u32>().unwrap();
144 assert_eq!((width, height), (expected_width, expected_height));
145 }
146 }
147
148 #[test]
149 fn test_invalid_resolution_format() {
150 let size_str = "invalid";
151 let parts: Vec<&str> = size_str.split(',').collect();
152 assert_eq!(parts.len(), 1);
153 }
154
155 #[test]
156 fn test_get_framebuffer_resolutions_funcs() {
157 use std::fs;
158 let tmp = std::env::temp_dir().join(format!(
159 "uconsole_fb_{}",
160 std::time::SystemTime::now()
161 .duration_since(std::time::UNIX_EPOCH)
162 .unwrap()
163 .as_millis()
164 ));
165 let _ = fs::create_dir_all(&tmp);
166 fs::write(tmp.join("virtual_size"), "1920,1080\n").unwrap();
167 fs::write(tmp.join("phys_size"), "268,150\n").unwrap();
168
169 let v = get_virtual_resolution(&tmp).unwrap();
170 assert_eq!(v, Some((1920u32, 1080u32)));
171 let p = get_physical_resolution(&tmp).unwrap();
172 assert_eq!(p, Some((268u32, 150u32)));
173 }
174
175 #[test]
176 fn test_pathbuf_join_operation() {
177 let base = PathBuf::from("/sys/class/graphics/fb0");
178 let virtual_size_path = base.join("virtual_size");
179 assert!(virtual_size_path.to_string_lossy().contains("virtual_size"));
180 }
181
182 #[test]
183 fn test_resolution_edge_cases() {
184 assert_eq!("0,0".split(',').count(), 2);
185 assert_eq!(
186 ("4294967295,4294967295".split(',').collect::<Vec<_>>().len()),
187 2
188 );
189 }
190}