java_manager/manager.rs
1// Copyright 2026 TaimWay
2//
3// @file: manager.rs
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17use std::collections::HashMap;
18
19use crate::errors::Result;
20use crate::info::JavaInfo;
21
22/// Manages multiple Java installations and provides convenient access methods.
23///
24/// The `JavaManager` struct provides functionality to:
25/// - Store and organize multiple Java installations
26/// - Filter installations by various criteria
27/// - Set default Java installations
28/// - Execute commands with specific Java versions
29///
30/// # Examples
31///
32/// ```rust
33/// use java_manager::{JavaManager, JavaInfo};
34///
35/// fn main() -> java_manager::Result<()> {
36/// // Create a manager and discover all Java installations
37/// let mut manager = JavaManager::new();
38/// manager.discover_installations()?;
39///
40/// // List all installations
41/// println!("Found {} Java installations:", manager.len());
42/// for java in manager.list() {
43/// println!(" - {}", java);
44/// }
45///
46/// // Get Java by version
47/// if let Some(java_11) = manager.get_by_version(11) {
48/// println!("Java 11: {}", java_11);
49/// }
50///
51/// Ok(())
52/// }
53/// ```
54pub struct JavaManager {
55 /// Vector of Java installations
56 java_installations: Vec<JavaInfo>,
57 /// Default Java installation index
58 default_index: Option<usize>,
59 /// Map of version to installation indices for quick lookup
60 version_map: HashMap<u32, Vec<usize>>,
61}
62
63impl JavaManager {
64 /// Creates a new empty `JavaManager`.
65 ///
66 /// # Returns
67 ///
68 /// A new `JavaManager` instance
69 ///
70 /// # Examples
71 ///
72 /// ```rust
73 /// use java_manager::JavaManager;
74 ///
75 /// let manager = JavaManager::new();
76 /// assert_eq!(manager.len(), 0);
77 /// ```
78 pub fn new() -> Self {
79 JavaManager {
80 java_installations: Vec::new(),
81 default_index: None,
82 version_map: HashMap::new(),
83 }
84 }
85
86 /// Discovers and adds all Java installations on the system.
87 ///
88 /// # Returns
89 ///
90 /// - `Ok(())` if discovery succeeds
91 /// - `Err(JavaLocatorError)` if an error occurs during discovery
92 ///
93 /// # Examples
94 ///
95 /// ```rust
96 /// use java_manager::JavaManager;
97 ///
98 /// fn main() -> java_manager::Result<()> {
99 /// let mut manager = JavaManager::new();
100 /// manager.discover_installations()?;
101 /// println!("Discovered {} Java installations", manager.len());
102 /// Ok(())
103 /// }
104 /// ```
105 pub fn discover_installations(&mut self) -> Result<()> {
106 let installations = crate::local::find_all_java_installations()?;
107
108 for installation in installations {
109 self.add(installation);
110 }
111
112 // Set the first installation as default if any exist
113 if !self.java_installations.is_empty() {
114 self.default_index = Some(0);
115 }
116
117 Ok(())
118 }
119
120 /// Adds a Java installation to the manager.
121 ///
122 /// # Arguments
123 ///
124 /// * `java_info` - Java installation information to add
125 ///
126 /// # Examples
127 ///
128 /// ```rust
129 /// use java_manager::{JavaManager, JavaInfo};
130 ///
131 /// let mut manager = JavaManager::new();
132 /// let java_info = JavaInfo::new("java", "/usr/bin/java", "11.0.12", "64-bit", "OpenJDK");
133 /// manager.add(java_info);
134 /// assert_eq!(manager.len(), 1);
135 /// ```
136 pub fn add(&mut self, java_info: JavaInfo) {
137 let index = self.java_installations.len();
138 self.java_installations.push(java_info.clone());
139
140 // Update version map for quick lookup
141 if let Some(version) = java_info.get_major_version() {
142 self.version_map
143 .entry(version)
144 .or_insert_with(Vec::new)
145 .push(index);
146 }
147
148 // Set as default if this is the first installation
149 if self.default_index.is_none() {
150 self.default_index = Some(index);
151 }
152 }
153
154 /// Gets a Java installation by index.
155 ///
156 /// # Arguments
157 ///
158 /// * `index` - Index of the Java installation to retrieve
159 ///
160 /// # Returns
161 ///
162 /// - `Some(&JavaInfo)` if the index is valid
163 /// - `None` if the index is out of bounds
164 ///
165 /// # Examples
166 ///
167 /// ```rust
168 /// use java_manager::JavaManager;
169 ///
170 /// let manager = JavaManager::new();
171 /// // Add some installations first...
172 /// // let java = manager.get(0);
173 /// ```
174 pub fn get(&self, index: usize) -> Option<&JavaInfo> {
175 self.java_installations.get(index)
176 }
177
178 /// Gets a Java installation by major version.
179 ///
180 /// If multiple installations have the same version, returns the first one.
181 ///
182 /// # Arguments
183 ///
184 /// * `version` - Major version to look for (e.g., 8, 11, 17)
185 ///
186 /// # Returns
187 ///
188 /// - `Some(&JavaInfo)` if a matching installation is found
189 /// - `None` if no installation with the specified version exists
190 ///
191 /// # Examples
192 ///
193 /// ```rust
194 /// use java_manager::JavaManager;
195 ///
196 /// let manager = JavaManager::new();
197 /// // Discover installations first...
198 /// // if let Some(java_11) = manager.get_by_version(11) {
199 /// // println!("Found Java 11: {}", java_11);
200 /// // }
201 /// ```
202 pub fn get_by_version(&self, version: u32) -> Option<&JavaInfo> {
203 self.version_map
204 .get(&version)
205 .and_then(|indices| indices.first())
206 .and_then(|&index| self.get(index))
207 }
208
209 /// Gets all Java installations of a specific major version.
210 ///
211 /// # Arguments
212 ///
213 /// * `version` - Major version to look for
214 ///
215 /// # Returns
216 ///
217 /// Vector of references to Java installations with the specified version
218 ///
219 /// # Examples
220 ///
221 /// ```rust
222 /// use java_manager::JavaManager;
223 ///
224 /// let manager = JavaManager::new();
225 /// // Discover installations first...
226 /// // let java_11_installations = manager.get_all_by_version(11);
227 /// // println!("Found {} Java 11 installations", java_11_installations.len());
228 /// ```
229 pub fn get_all_by_version(&self, version: u32) -> Vec<&JavaInfo> {
230 self.version_map
231 .get(&version)
232 .map(|indices| {
233 indices.iter()
234 .filter_map(|&index| self.get(index))
235 .collect()
236 })
237 .unwrap_or_default()
238 }
239
240 /// Gets the default Java installation.
241 ///
242 /// # Returns
243 ///
244 /// - `Some(&JavaInfo)` if a default installation is set
245 /// - `None` if no installations exist or no default is set
246 ///
247 /// # Examples
248 ///
249 /// ```rust
250 /// use java_manager::JavaManager;
251 ///
252 /// let manager = JavaManager::new();
253 /// // Discover installations first...
254 /// // if let Some(default_java) = manager.get_default() {
255 /// // println!("Default Java: {}", default_java);
256 /// // }
257 /// ```
258 pub fn get_default(&self) -> Option<&JavaInfo> {
259 self.default_index.and_then(|index| self.get(index))
260 }
261
262 /// Sets the default Java installation by index.
263 ///
264 /// # Arguments
265 ///
266 /// * `index` - Index of the Java installation to set as default
267 ///
268 /// # Returns
269 ///
270 /// - `true` if the index is valid and default was set
271 /// - `false` if the index is out of bounds
272 ///
273 /// # Examples
274 ///
275 /// ```rust
276 /// use java_manager::JavaManager;
277 ///
278 /// let mut manager = JavaManager::new();
279 /// // Add installations first...
280 /// // let success = manager.set_default(0);
281 /// ```
282 pub fn set_default(&mut self, index: usize) -> bool {
283 if index < self.java_installations.len() {
284 self.default_index = Some(index);
285 true
286 } else {
287 false
288 }
289 }
290
291 /// Sets the default Java installation by version.
292 ///
293 /// If multiple installations have the same version, sets the first one as default.
294 ///
295 /// # Arguments
296 ///
297 /// * `version` - Major version to set as default
298 ///
299 /// # Returns
300 ///
301 /// - `true` if a matching installation was found and set as default
302 /// - `false` if no installation with the specified version exists
303 ///
304 /// # Examples
305 ///
306 /// ```rust
307 /// use java_manager::JavaManager;
308 ///
309 /// let mut manager = JavaManager::new();
310 /// // Discover installations first...
311 /// // let success = manager.set_default_by_version(11);
312 /// ```
313 pub fn set_default_by_version(&mut self, version: u32) -> bool {
314 if let Some(&index) = self.version_map
315 .get(&version)
316 .and_then(|indices| indices.first())
317 {
318 self.default_index = Some(index);
319 true
320 } else {
321 false
322 }
323 }
324
325 /// Returns a reference to all Java installations.
326 ///
327 /// # Returns
328 ///
329 /// Reference to vector of all Java installations
330 ///
331 /// # Examples
332 ///
333 /// ```rust
334 /// use java_manager::JavaManager;
335 ///
336 /// let manager = JavaManager::new();
337 /// // Discover installations first...
338 /// // let all_java = manager.list();
339 /// // for java in all_java {
340 /// // println!("{}", java);
341 /// // }
342 /// ```
343 pub fn list(&self) -> &Vec<JavaInfo> {
344 &self.java_installations
345 }
346
347 /// Returns the number of Java installations in the manager.
348 ///
349 /// # Returns
350 ///
351 /// Number of Java installations
352 ///
353 /// # Examples
354 ///
355 /// ```rust
356 /// use java_manager::JavaManager;
357 ///
358 /// let manager = JavaManager::new();
359 /// assert_eq!(manager.len(), 0);
360 /// ```
361 pub fn len(&self) -> usize {
362 self.java_installations.len()
363 }
364
365 /// Checks if the manager has any Java installations.
366 ///
367 /// # Returns
368 ///
369 /// - `true` if there are no Java installations
370 /// - `false` if there is at least one Java installation
371 ///
372 /// # Examples
373 ///
374 /// ```rust
375 /// use java_manager::JavaManager;
376 ///
377 /// let manager = JavaManager::new();
378 /// assert!(manager.is_empty());
379 /// ```
380 pub fn is_empty(&self) -> bool {
381 self.java_installations.is_empty()
382 }
383
384 /// Filters Java installations by supplier/vendor.
385 ///
386 /// # Arguments
387 ///
388 /// * `supplier` - Supplier name to filter by (case-insensitive)
389 ///
390 /// # Returns
391 ///
392 /// Vector of references to Java installations from the specified supplier
393 ///
394 /// # Examples
395 ///
396 /// ```rust
397 /// use java_manager::JavaManager;
398 ///
399 /// let manager = JavaManager::new();
400 /// // Discover installations first...
401 /// // let openjdk_installations = manager.filter_by_supplier("OpenJDK");
402 /// ```
403 pub fn filter_by_supplier(&self, supplier: &str) -> Vec<&JavaInfo> {
404 let supplier_lower = supplier.to_lowercase();
405 self.java_installations
406 .iter()
407 .filter(|info| info.suppliers.to_lowercase().contains(&supplier_lower))
408 .collect()
409 }
410
411 /// Filters Java installations by architecture.
412 ///
413 /// # Arguments
414 ///
415 /// * `architecture` - Architecture to filter by (e.g., "64-bit", "32-bit")
416 ///
417 /// # Returns
418 ///
419 /// Vector of references to Java installations with the specified architecture
420 ///
421 /// # Examples
422 ///
423 /// ```rust
424 /// use java_manager::JavaManager;
425 ///
426 /// let manager = JavaManager::new();
427 /// // Discover installations first...
428 /// // let x64_installations = manager.filter_by_architecture("64-bit");
429 /// ```
430 pub fn filter_by_architecture(&self, architecture: &str) -> Vec<&JavaInfo> {
431 self.java_installations
432 .iter()
433 .filter(|info| info.architecture == architecture)
434 .collect()
435 }
436
437 /// Executes a Java command using the default Java installation.
438 ///
439 /// # Arguments
440 ///
441 /// * `args` - Command-line arguments to pass to Java
442 ///
443 /// # Returns
444 ///
445 /// - `Ok(String)` - Command output as a string
446 /// - `Err(std::io::Error)` - If the command fails to execute or no default Java is set
447 ///
448 /// # Examples
449 ///
450 /// ```rust
451 /// use java_manager::JavaManager;
452 ///
453 /// fn main() -> std::io::Result<()> {
454 /// let mut manager = JavaManager::new();
455 /// manager.discover_installations()?;
456 ///
457 /// let output = manager.execute_default(&["-version"])?;
458 /// println!("Output:\n{}", output);
459 /// Ok(())
460 /// }
461 /// ```
462 pub fn execute_default(&self, args: &[&str]) -> std::io::Result<String> {
463 self.get_default()
464 .ok_or_else(|| std::io::Error::new(
465 std::io::ErrorKind::NotFound,
466 "No default Java installation set"
467 ))?
468 .execute_with_output(args)
469 }
470
471 /// Executes a Java command using a specific Java version.
472 ///
473 /// # Arguments
474 ///
475 /// * `version` - Major version of Java to use
476 /// * `args` - Command-line arguments to pass to Java
477 ///
478 /// # Returns
479 ///
480 /// - `Ok(String)` - Command output as a string
481 /// - `Err(std::io::Error)` - If the command fails to execute or the version is not found
482 ///
483 /// # Examples
484 ///
485 /// ```rust
486 /// use java_manager::JavaManager;
487 ///
488 /// fn main() -> std::io::Result<()> {
489 /// let mut manager = JavaManager::new();
490 /// manager.discover_installations()?;
491 ///
492 /// let output = manager.execute_with_version(11, &["-version"])?;
493 /// println!("Java 11 output:\n{}", output);
494 /// Ok(())
495 /// }
496 /// ```
497 pub fn execute_with_version(&self, version: u32, args: &[&str]) -> std::io::Result<String> {
498 self.get_by_version(version)
499 .ok_or_else(|| std::io::Error::new(
500 std::io::ErrorKind::NotFound,
501 format!("Java version {} not found", version)
502 ))?
503 .execute_with_output(args)
504 }
505
506 /// Returns a summary of Java installations by version.
507 ///
508 /// # Returns
509 ///
510 /// HashMap mapping major versions to counts of installations
511 ///
512 /// # Examples
513 ///
514 /// ```rust
515 /// use java_manager::JavaManager;
516 ///
517 /// let manager = JavaManager::new();
518 /// // Discover installations first...
519 /// // let summary = manager.get_version_summary();
520 /// // for (version, count) in summary {
521 /// // println!("Java {}: {} installations", version, count);
522 /// // }
523 /// ```
524 pub fn get_version_summary(&self) -> HashMap<u32, usize> {
525 let mut summary = HashMap::new();
526
527 for info in &self.java_installations {
528 if let Some(version) = info.get_major_version() {
529 *summary.entry(version).or_insert(0) += 1;
530 }
531 }
532
533 summary
534 }
535
536 /// Clears all Java installations from the manager.
537 ///
538 /// # Examples
539 ///
540 /// ```rust
541 /// use java_manager::JavaManager;
542 ///
543 /// let mut manager = JavaManager::new();
544 /// // Add some installations...
545 /// manager.clear();
546 /// assert!(manager.is_empty());
547 /// ```
548 pub fn clear(&mut self) {
549 self.java_installations.clear();
550 self.version_map.clear();
551 self.default_index = None;
552 }
553}
554
555impl Default for JavaManager {
556 /// Creates a new `JavaManager` with default settings.
557 ///
558 /// # Returns
559 ///
560 /// A new `JavaManager` instance
561 fn default() -> Self {
562 Self::new()
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569
570 /// Tests creating a new JavaManager
571 #[test]
572 fn test_new_manager() {
573 let manager = JavaManager::new();
574 assert!(manager.is_empty());
575 assert_eq!(manager.len(), 0);
576 assert!(manager.get_default().is_none());
577 }
578
579 /// Tests adding Java installations to the manager
580 #[test]
581 fn test_add_java() {
582 let mut manager = JavaManager::new();
583
584 let java1 = JavaInfo::new("java", "/usr/bin/java1", "11.0.12", "64-bit", "OpenJDK");
585 let java2 = JavaInfo::new("java", "/usr/bin/java2", "1.8.0_312", "64-bit", "Oracle");
586
587 manager.add(java1.clone());
588 manager.add(java2.clone());
589
590 assert_eq!(manager.len(), 2);
591 assert!(!manager.is_empty());
592
593 // First added should be default
594 assert!(manager.get_default().is_some());
595 assert_eq!(manager.get_default().unwrap().path, java1.path);
596 }
597
598 /// Tests getting Java installations by index
599 #[test]
600 fn test_get_by_index() {
601 let mut manager = JavaManager::new();
602
603 let java1 = JavaInfo::new("java", "/usr/bin/java1", "11.0.12", "64-bit", "OpenJDK");
604 let java2 = JavaInfo::new("java", "/usr/bin/java2", "1.8.0_312", "64-bit", "Oracle");
605
606 manager.add(java1);
607 manager.add(java2);
608
609 assert!(manager.get(0).is_some());
610 assert!(manager.get(1).is_some());
611 assert!(manager.get(2).is_none());
612 }
613
614 /// Tests getting Java installations by version
615 #[test]
616 fn test_get_by_version() {
617 let mut manager = JavaManager::new();
618
619 let java11 = JavaInfo::new("java", "/usr/bin/java11", "11.0.12", "64-bit", "OpenJDK");
620 let java8 = JavaInfo::new("java", "/usr/bin/java8", "1.8.0_312", "64-bit", "Oracle");
621
622 manager.add(java11);
623 manager.add(java8);
624
625 // Test getting Java 11
626 let java_11 = manager.get_by_version(11);
627 assert!(java_11.is_some());
628 assert_eq!(java_11.unwrap().get_major_version(), Some(11));
629
630 // Test getting Java 8
631 let java_8 = manager.get_by_version(8);
632 assert!(java_8.is_some());
633 assert_eq!(java_8.unwrap().get_major_version(), Some(8));
634
635 // Test getting non-existent version
636 let java_17 = manager.get_by_version(17);
637 assert!(java_17.is_none());
638 }
639
640 /// Tests getting all Java installations by version
641 #[test]
642 fn test_get_all_by_version() {
643 let mut manager = JavaManager::new();
644
645 // Add multiple Java 11 installations
646 let java11_1 = JavaInfo::new("java", "/usr/bin/java11_1", "11.0.12", "64-bit", "OpenJDK");
647 let java11_2 = JavaInfo::new("java", "/usr/bin/java11_2", "11.0.13", "64-bit", "Oracle");
648 let java8 = JavaInfo::new("java", "/usr/bin/java8", "1.8.0_312", "64-bit", "OpenJDK");
649
650 manager.add(java11_1);
651 manager.add(java11_2);
652 manager.add(java8);
653
654 // Get all Java 11 installations
655 let java11_installations = manager.get_all_by_version(11);
656 assert_eq!(java11_installations.len(), 2);
657
658 // Get all Java 8 installations
659 let java8_installations = manager.get_all_by_version(8);
660 assert_eq!(java8_installations.len(), 1);
661
662 // Get all Java 17 installations (none)
663 let java17_installations = manager.get_all_by_version(17);
664 assert_eq!(java17_installations.len(), 0);
665 }
666
667 /// Tests setting and getting default Java installation
668 #[test]
669 fn test_set_default() {
670 let mut manager = JavaManager::new();
671
672 let java1 = JavaInfo::new("java", "/usr/bin/java1", "11.0.12", "64-bit", "OpenJDK");
673 let java2 = JavaInfo::new("java", "/usr/bin/java2", "1.8.0_312", "64-bit", "Oracle");
674
675 manager.add(java1.clone());
676 manager.add(java2.clone());
677
678 // First added should be default
679 assert_eq!(manager.get_default().unwrap().path, java1.path);
680
681 // Set second as default
682 assert!(manager.set_default(1));
683 assert_eq!(manager.get_default().unwrap().path, java2.path);
684
685 // Try to set invalid index
686 assert!(!manager.set_default(5));
687 assert_eq!(manager.get_default().unwrap().path, java2.path); // Should remain unchanged
688 }
689
690 /// Tests setting default by version
691 #[test]
692 fn test_set_default_by_version() {
693 let mut manager = JavaManager::new();
694
695 let java11 = JavaInfo::new("java", "/usr/bin/java11", "11.0.12", "64-bit", "OpenJDK");
696 let java8 = JavaInfo::new("java", "/usr/bin/java8", "1.8.0_312", "64-bit", "Oracle");
697
698 manager.add(java11.clone());
699 manager.add(java8.clone());
700
701 // Set default to Java 8
702 assert!(manager.set_default_by_version(8));
703 assert_eq!(manager.get_default().unwrap().path, java8.path);
704
705 // Set default to Java 11
706 assert!(manager.set_default_by_version(11));
707 assert_eq!(manager.get_default().unwrap().path, java11.path);
708
709 // Try to set non-existent version
710 assert!(!manager.set_default_by_version(17));
711 assert_eq!(manager.get_default().unwrap().path, java11.path); // Should remain unchanged
712 }
713
714 /// Tests filtering Java installations by supplier
715 #[test]
716 fn test_filter_by_supplier() {
717 let mut manager = JavaManager::new();
718
719 let java1 = JavaInfo::new("java", "/usr/bin/java1", "11.0.12", "64-bit", "OpenJDK");
720 let java2 = JavaInfo::new("java", "/usr/bin/java2", "11.0.13", "64-bit", "Oracle");
721 let java3 = JavaInfo::new("java", "/usr/bin/java3", "1.8.0_312", "64-bit", "OpenJDK");
722
723 manager.add(java1);
724 manager.add(java2);
725 manager.add(java3);
726
727 // Filter by OpenJDK (case-insensitive)
728 let openjdk_installations = manager.filter_by_supplier("OpenJDK");
729 assert_eq!(openjdk_installations.len(), 2);
730
731 // Filter by Oracle
732 let oracle_installations = manager.filter_by_supplier("Oracle");
733 assert_eq!(oracle_installations.len(), 1);
734
735 // Filter by non-existent supplier
736 let ibm_installations = manager.filter_by_supplier("IBM");
737 assert_eq!(ibm_installations.len(), 0);
738 }
739
740 /// Tests filtering Java installations by architecture
741 #[test]
742 fn test_filter_by_architecture() {
743 let mut manager = JavaManager::new();
744
745 let java64 = JavaInfo::new("java", "/usr/bin/java64", "11.0.12", "64-bit", "OpenJDK");
746 let java32 = JavaInfo::new("java", "/usr/bin/java32", "1.8.0_312", "32-bit", "Oracle");
747 let java64_2 = JavaInfo::new("java", "/usr/bin/java64_2", "17.0.1", "64-bit", "OpenJDK");
748
749 manager.add(java64);
750 manager.add(java32);
751 manager.add(java64_2);
752
753 // Filter 64-bit installations
754 let x64_installations = manager.filter_by_architecture("64-bit");
755 assert_eq!(x64_installations.len(), 2);
756
757 // Filter 32-bit installations
758 let x86_installations = manager.filter_by_architecture("32-bit");
759 assert_eq!(x86_installations.len(), 1);
760
761 // Filter non-existent architecture
762 let unknown_installations = manager.filter_by_architecture("Unknown");
763 assert_eq!(unknown_installations.len(), 0);
764 }
765
766 /// Tests getting version summary
767 #[test]
768 fn test_get_version_summary() {
769 let mut manager = JavaManager::new();
770
771 // Add multiple versions
772 let java11_1 = JavaInfo::new("java", "/usr/bin/java11_1", "11.0.12", "64-bit", "OpenJDK");
773 let java11_2 = JavaInfo::new("java", "/usr/bin/java11_2", "11.0.13", "64-bit", "Oracle");
774 let java8 = JavaInfo::new("java", "/usr/bin/java8", "1.8.0_312", "64-bit", "OpenJDK");
775 let java17 = JavaInfo::new("java", "/usr/bin/java17", "17.0.1", "64-bit", "OpenJDK");
776 let java_invalid = JavaInfo::new("java", "/usr/bin/java_invalid", "invalid", "64-bit", "Unknown");
777
778 manager.add(java11_1);
779 manager.add(java11_2);
780 manager.add(java8);
781 manager.add(java17);
782 manager.add(java_invalid);
783
784 let summary = manager.get_version_summary();
785
786 assert_eq!(summary.get(&11), Some(&2)); // Two Java 11 installations
787 assert_eq!(summary.get(&8), Some(&1)); // One Java 8 installation
788 assert_eq!(summary.get(&17), Some(&1)); // One Java 17 installation
789 assert_eq!(summary.get(&99), None); // No Java 99 installations
790 }
791
792 /// Tests clearing all installations
793 #[test]
794 fn test_clear() {
795 let mut manager = JavaManager::new();
796
797 let java1 = JavaInfo::new("java", "/usr/bin/java1", "11.0.12", "64-bit", "OpenJDK");
798 let java2 = JavaInfo::new("java", "/usr/bin/java2", "1.8.0_312", "64-bit", "Oracle");
799
800 manager.add(java1);
801 manager.add(java2);
802
803 assert_eq!(manager.len(), 2);
804 assert!(!manager.is_empty());
805
806 manager.clear();
807
808 assert_eq!(manager.len(), 0);
809 assert!(manager.is_empty());
810 assert!(manager.get_default().is_none());
811 }
812
813 /// Tests the list method
814 #[test]
815 fn test_list() {
816 let mut manager = JavaManager::new();
817
818 let java1 = JavaInfo::new("java", "/usr/bin/java1", "11.0.12", "64-bit", "OpenJDK");
819 let java2 = JavaInfo::new("java", "/usr/bin/java2", "1.8.0_312", "64-bit", "Oracle");
820
821 manager.add(java1);
822 manager.add(java2);
823
824 let list = manager.list();
825 assert_eq!(list.len(), 2);
826
827 // Verify we can iterate over the list
828 for java in list {
829 assert!(java.is_valid() || !std::path::Path::new(&java.path).exists());
830 }
831 }
832
833 /// Tests the Default trait implementation
834 #[test]
835 fn test_default() {
836 let manager = JavaManager::default();
837 assert!(manager.is_empty());
838 assert_eq!(manager.len(), 0);
839 }
840
841 /// Tests discovering installations (if Java is available)
842 #[test]
843 fn test_discover_installations() {
844 let mut manager = JavaManager::new();
845 let result = manager.discover_installations();
846
847 // Discovery might succeed or fail depending on whether Java is installed
848 if result.is_ok() {
849 // If discovery succeeded, there should be at least one installation
850 // (unless the system has no Java at all)
851 println!("Discovered {} Java installations", manager.len());
852
853 if !manager.is_empty() {
854 assert!(manager.get_default().is_some());
855
856 // List all discovered installations
857 for (i, java) in manager.list().iter().enumerate() {
858 println!("{}. {}", i + 1, java);
859 }
860 }
861 } else {
862 println!("Discovery failed (Java may not be installed)");
863 }
864 }
865}