1use tracing::{info_span, trace};
2
3use super::{Dependency, Package};
4
5pub trait Visitor {
7 fn visit(&mut self, package: &mut Package)
9 where
10 Self: Sized,
11 {
12 self.visit_package(package);
13
14 for dependency in package.dependencies_iter() {
15 let dependency_span = info_span!(
16 "processing dependency",
17 name = dependency.name,
18 package_name = dependency.package.borrow().name,
19 optional = dependency.optional,
20 );
21 let _dependency_span_guard = dependency_span.enter();
22
23 if !dependency.optional {
24 self.visit_dependency(dependency);
25
26 dependency.package.borrow_mut().visit(self);
27 }
28 }
29 }
30
31 fn visit_package(&mut self, _package: &mut Package) {}
33
34 fn visit_dependency(&mut self, _dependency: &Dependency) {}
36}
37
38pub struct ResolveVisitor;
40
41impl Visitor for ResolveVisitor {
42 fn visit_dependency(&mut self, dependency: &Dependency) {
43 add_default(dependency);
44 activate_features(dependency);
45 }
46
47 fn visit_package(&mut self, package: &mut Package) {
48 loop {
49 let new_features = unpack_features(package);
50
51 if !new_features.is_empty() {
52 trace!(?new_features, "adding new features");
53
54 package.enabled_features.extend(new_features);
55 } else {
56 break;
57 }
58 }
59
60 unpack_optionals_features(package);
61 }
62}
63
64fn add_default(dependency: &Dependency) {
67 if dependency.uses_default_features
68 && dependency.package.borrow().features.contains_key("default")
69 {
70 trace!("enabling default feature");
71
72 dependency
73 .package
74 .borrow_mut()
75 .enabled_features
76 .insert("default".to_string());
77 }
78}
79
80fn activate_features(dependency: &Dependency) {
82 if !dependency.features.is_empty() {
83 let features: Vec<String> = dependency
84 .features
85 .clone()
86 .iter()
87 .filter(|&f| dependency.package.borrow().features.contains_key(f))
88 .cloned()
89 .collect();
90
91 trace!(?features, "enabling features");
92
93 dependency
94 .package
95 .borrow_mut()
96 .enabled_features
97 .extend(features);
98 }
99}
100
101fn unpack_features(package: &mut Package) -> Vec<String> {
103 package
104 .enabled_features
105 .iter()
106 .filter_map(|f| package.features.get(f))
107 .flatten()
108 .cloned()
109 .filter(|f| !package.enabled_features.contains(f)) .filter_map(|f| {
111 if let Some(dependency_name) = f.strip_prefix("dep:") {
114 if let Some(dependency) = package
115 .dependencies
116 .iter_mut()
117 .chain(package.build_dependencies.iter_mut())
118 .find(|d| d.name == dependency_name)
119 {
120 trace!(name = dependency_name, "activating optional dependency");
121 dependency.optional = false;
122 }
123
124 return None;
126 } else {
127 if let Some((dependency_name, feature)) = f.split_once('/') {
130 if let Some(dependency) = package
131 .dependencies
132 .iter_mut()
133 .chain(package.build_dependencies.iter_mut())
134 .find(|d| d.name == dependency_name)
135 {
136 let feature = feature.to_string();
137
138 if !dependency.features.contains(&feature) {
139 dependency.features.push(feature);
140 }
141
142 return Some(dependency_name.to_string());
143 }
144 }
145 }
146
147 Some(f)
148 })
149 .filter(|f| !package.enabled_features.contains(f)) .collect()
151}
152
153fn unpack_optionals_features(package: &mut Package) {
156 let new_dependencies_features: Vec<_> = package
157 .enabled_features
158 .iter()
159 .filter_map(|f| f.split_once("?/"))
160 .map(|(d, f)| (d.to_string(), f.to_string()))
161 .collect();
162
163 for (dependency_name, feature) in new_dependencies_features {
164 if let Some(dependency) = package
165 .dependencies_iter_mut()
166 .find(|d| d.name == dependency_name && !d.optional)
167 {
168 if !dependency.features.contains(&feature) {
169 dependency.features.push(feature.clone());
170 }
171
172 trace!(
173 dependency = dependency_name,
174 feature,
175 "adding feature on optional dependency"
176 );
177 }
178
179 package
180 .enabled_features
181 .remove(&format!("{dependency_name}?/{feature}"));
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use std::{cell::RefCell, collections::HashMap, rc::Rc};
188
189 use crate::models::cargo::{Dependency, Package};
190
191 use pretty_assertions::assert_eq;
192
193 fn make_package_node(
194 name: &str,
195 features: Vec<(&str, Vec<&str>)>,
196 dependency: Option<Dependency>,
197 ) -> Package {
198 let dependencies = if let Some(dependency) = dependency {
199 vec![dependency]
200 } else {
201 Default::default()
202 };
203
204 Package {
205 name: name.to_string(),
206 lib_name: None,
207 version: "0.1.0".parse().unwrap(),
208 source: "sha".into(),
209 lib_path: None,
210 build_path: None,
211 proc_macro: false,
212 dependencies,
213 build_dependencies: Default::default(),
214 features: HashMap::from_iter(features.into_iter().map(|(b, d)| {
215 (
216 b.to_string(),
217 d.into_iter().map(ToString::to_string).collect(),
218 )
219 })),
220 enabled_features: Default::default(),
221 edition: "2021".to_string(),
222 }
223 }
224
225 #[test]
227 fn no_defaults() {
228 let mut child = make_package_node(
229 "child",
230 vec![
231 ("default", vec!["one", "two"]),
232 ("one", vec![]),
233 ("two", vec![]),
234 ],
235 None,
236 );
237
238 let mut input = make_package_node(
239 "parent",
240 vec![],
241 Some(Dependency {
242 name: "child".to_string(),
243 package: RefCell::new(child.clone()).into(),
244 optional: false,
245 uses_default_features: false,
246 features: vec!["one".to_string()],
247 }),
248 );
249
250 input.resolve();
251
252 child.enabled_features.insert("one".to_string());
253 let expected = make_package_node(
254 "parent",
255 vec![],
256 Some(Dependency {
257 name: "child".to_string(),
258 package: RefCell::new(child.clone()).into(),
259 optional: false,
260 uses_default_features: false,
261 features: vec!["one".to_string()],
262 }),
263 );
264
265 assert_eq!(input, expected);
266 }
267
268 #[test]
270 fn defaults() {
271 let mut child = make_package_node(
272 "child",
273 vec![
274 ("default", vec!["one", "two"]),
275 ("one", vec![]),
276 ("two", vec![]),
277 ],
278 None,
279 );
280
281 let mut input = make_package_node(
282 "parent",
283 vec![],
284 Some(Dependency {
285 name: "child".to_string(),
286 package: RefCell::new(child.clone()).into(),
287 optional: false,
288 uses_default_features: true,
289 features: vec![],
290 }),
291 );
292
293 input.resolve();
294
295 child.enabled_features.extend([
296 "one".to_string(),
297 "two".to_string(),
298 "default".to_string(),
299 ]);
300 let expected = make_package_node(
301 "parent",
302 vec![],
303 Some(Dependency {
304 name: "child".to_string(),
305 package: RefCell::new(child.clone()).into(),
306 optional: false,
307 uses_default_features: true,
308 features: vec![],
309 }),
310 );
311
312 assert_eq!(input, expected);
313 }
314
315 #[test]
317 fn defaults_chain() {
318 let mut child = make_package_node(
319 "child",
320 vec![
321 ("default", vec!["one"]),
322 ("one", vec!["two"]),
323 ("two", vec![]),
324 ],
325 None,
326 );
327
328 let mut input = make_package_node(
329 "parent",
330 vec![],
331 Some(Dependency {
332 name: "child".to_string(),
333 package: RefCell::new(child.clone()).into(),
334 optional: false,
335 uses_default_features: true,
336 features: vec![],
337 }),
338 );
339
340 input.resolve();
341
342 child.enabled_features.extend([
343 "one".to_string(),
344 "two".to_string(),
345 "default".to_string(),
346 ]);
347 let expected = make_package_node(
348 "parent",
349 vec![],
350 Some(Dependency {
351 name: "child".to_string(),
352 package: RefCell::new(child.clone()).into(),
353 optional: false,
354 uses_default_features: true,
355 features: vec![],
356 }),
357 );
358
359 assert_eq!(input, expected);
360 }
361
362 #[test]
364 fn optional_no_defaults() {
365 let child = make_package_node(
366 "child",
367 vec![
368 ("default", vec!["one", "two"]),
369 ("one", vec![]),
370 ("two", vec![]),
371 ],
372 None,
373 );
374 let build = make_package_node("build", vec![("default", vec!["hi"]), ("hi", vec![])], None);
375
376 let mut input = make_package_node(
377 "parent",
378 vec![],
379 Some(Dependency {
380 name: "child".to_string(),
381 package: RefCell::new(child.clone()).into(),
382 optional: true,
383 uses_default_features: true,
384 features: vec![],
385 }),
386 );
387 input.build_dependencies.push(Dependency {
388 name: "build".to_string(),
389 package: RefCell::new(build.clone()).into(),
390 optional: true,
391 uses_default_features: true,
392 features: vec![],
393 });
394
395 input.resolve();
396
397 let mut expected = make_package_node(
398 "parent",
399 vec![],
400 Some(Dependency {
401 name: "child".to_string(),
402 package: RefCell::new(child).into(),
403 optional: true,
404 uses_default_features: true,
405 features: vec![],
406 }),
407 );
408 expected.build_dependencies.push(Dependency {
409 name: "build".to_string(),
410 package: RefCell::new(build).into(),
411 optional: true,
412 uses_default_features: true,
413 features: vec![],
414 });
415
416 assert_eq!(input, expected);
417 }
418
419 #[test]
421 fn optional_features() {
422 let child = make_package_node("child", vec![("one", vec![]), ("two", vec![])], None);
423 let build = make_package_node("build", vec![("hi", vec![])], None);
424
425 let mut input = make_package_node(
426 "parent",
427 vec![],
428 Some(Dependency {
429 name: "child".to_string(),
430 package: RefCell::new(child.clone()).into(),
431 optional: true,
432 uses_default_features: true,
433 features: vec!["one".to_string()],
434 }),
435 );
436 input.build_dependencies.push(Dependency {
437 name: "build".to_string(),
438 package: RefCell::new(build.clone()).into(),
439 optional: true,
440 uses_default_features: true,
441 features: vec!["hi".to_string()],
442 });
443
444 input.resolve();
445
446 let mut expected = make_package_node(
447 "parent",
448 vec![],
449 Some(Dependency {
450 name: "child".to_string(),
451 package: RefCell::new(child).into(),
452 optional: true,
453 uses_default_features: true,
454 features: vec!["one".to_string()],
455 }),
456 );
457 expected.build_dependencies.push(Dependency {
458 name: "build".to_string(),
459 package: RefCell::new(build).into(),
460 optional: true,
461 uses_default_features: true,
462 features: vec!["hi".to_string()],
463 });
464
465 assert_eq!(input, expected);
466 }
467
468 #[test]
470 fn chain() {
471 let mut child = make_package_node(
472 "child",
473 vec![
474 ("one", vec!["two"]),
475 ("two", vec!["three"]),
476 ("three", vec![]),
477 ],
478 None,
479 );
480 let mut build = make_package_node(
481 "build",
482 vec![("hi", vec!["world"]), ("world", vec![])],
483 None,
484 );
485
486 let mut input = make_package_node(
487 "parent",
488 vec![],
489 Some(Dependency {
490 name: "child".to_string(),
491 package: RefCell::new(child.clone()).into(),
492 optional: false,
493 uses_default_features: true,
494 features: vec!["one".to_string()],
495 }),
496 );
497 input.build_dependencies.push(Dependency {
498 name: "build".to_string(),
499 package: RefCell::new(build.clone()).into(),
500 optional: false,
501 uses_default_features: true,
502 features: vec!["hi".to_string()],
503 });
504
505 input.resolve();
506
507 child
508 .enabled_features
509 .extend(["one".to_string(), "two".to_string(), "three".to_string()]);
510 build
511 .enabled_features
512 .extend(["hi".to_string(), "world".to_string()]);
513
514 let mut expected = make_package_node(
515 "parent",
516 vec![],
517 Some(Dependency {
518 name: "child".to_string(),
519 package: RefCell::new(child.clone()).into(),
520 optional: false,
521 uses_default_features: true,
522 features: vec!["one".to_string()],
523 }),
524 );
525 expected.build_dependencies.push(Dependency {
526 name: "build".to_string(),
527 package: RefCell::new(build.clone()).into(),
528 optional: false,
529 uses_default_features: true,
530 features: vec!["hi".to_string()],
531 });
532
533 assert_eq!(input, expected);
534 }
535
536 #[test]
538 fn feature_dependency() {
539 let mut optional = make_package_node("optional", vec![("feature", vec![])], None);
540 let mut optional_build =
541 make_package_node("optional", vec![("build_feature", vec![])], None);
542
543 let mut child = make_package_node(
544 "child",
545 vec![
546 ("one", vec!["optional"]),
547 ("optional", vec!["dep:optional"]),
548 ],
549 Some(Dependency {
550 name: "optional".to_string(),
551 package: RefCell::new(optional.clone()).into(),
552 optional: true,
553 uses_default_features: true,
554 features: vec!["feature".to_string()],
555 }),
556 );
557 let mut build = make_package_node(
558 "build",
559 vec![("hi", vec!["dep:optional"])],
560 Some(Dependency {
561 name: "optional".to_string(),
562 package: RefCell::new(optional_build.clone()).into(),
563 optional: true,
564 uses_default_features: true,
565 features: vec!["build_feature".to_string()],
566 }),
567 );
568
569 let mut input = make_package_node(
570 "parent",
571 vec![],
572 Some(Dependency {
573 name: "child".to_string(),
574 package: RefCell::new(child.clone()).into(),
575 optional: false,
576 uses_default_features: true,
577 features: vec!["one".to_string()],
578 }),
579 );
580 input.build_dependencies.push(Dependency {
581 name: "build".to_string(),
582 package: RefCell::new(build.clone()).into(),
583 optional: false,
584 uses_default_features: true,
585 features: vec!["hi".to_string()],
586 });
587
588 input.resolve();
589
590 optional.enabled_features.extend(["feature".to_string()]);
591 optional_build
592 .enabled_features
593 .extend(["build_feature".to_string()]);
594
595 child.dependencies[0].optional = false;
596 child.dependencies[0].package = RefCell::new(optional).into();
597 child
598 .enabled_features
599 .extend(["one".to_string(), "optional".to_string()]);
600
601 build.dependencies[0].optional = false;
602 build.dependencies[0].package = RefCell::new(optional_build).into();
603 build.enabled_features.extend(["hi".to_string()]);
604
605 let mut expected = make_package_node(
606 "parent",
607 vec![],
608 Some(Dependency {
609 name: "child".to_string(),
610 package: RefCell::new(child.clone()).into(),
611 optional: false,
612 uses_default_features: true,
613 features: vec!["one".to_string()],
614 }),
615 );
616 expected.build_dependencies.push(Dependency {
617 name: "build".to_string(),
618 package: RefCell::new(build.clone()).into(),
619 optional: false,
620 uses_default_features: true,
621 features: vec!["hi".to_string()],
622 });
623
624 assert_eq!(input, expected);
625 }
626
627 #[test]
629 fn feature_renamed_dependency() {
630 let rename = make_package_node("rename", vec![], None);
631 let build_rename = make_package_node("build_rename", vec![], None);
632 let mut child = make_package_node(
633 "child",
634 vec![
635 ("new_name", vec!["dep:new_name"]),
636 ("new_build_name", vec!["dep:new_build_name"]),
637 ],
638 Some(Dependency {
639 name: "new_name".to_string(),
640 package: RefCell::new(rename.clone()).into(),
641 optional: true,
642 uses_default_features: true,
643 features: vec![],
644 }),
645 );
646 child.build_dependencies.push(Dependency {
647 name: "new_build_name".to_string(),
648 package: RefCell::new(build_rename.clone()).into(),
649 optional: true,
650 uses_default_features: true,
651 features: vec![],
652 });
653
654 let mut input = make_package_node(
655 "parent",
656 vec![],
657 Some(Dependency {
658 name: "child".to_string(),
659 package: RefCell::new(child.clone()).into(),
660 optional: false,
661 uses_default_features: true,
662 features: vec!["new_name".to_string(), "new_build_name".to_string()],
663 }),
664 );
665
666 input.resolve();
667
668 child.dependencies[0].optional = false;
669 child.dependencies[0].package = RefCell::new(rename).into();
670 child.build_dependencies[0].optional = false;
671 child.build_dependencies[0].package = RefCell::new(build_rename).into();
672 child
673 .enabled_features
674 .extend(["new_name".to_string(), "new_build_name".to_string()]);
675
676 let expected = make_package_node(
677 "parent",
678 vec![],
679 Some(Dependency {
680 name: "child".to_string(),
681 package: RefCell::new(child.clone()).into(),
682 optional: false,
683 uses_default_features: true,
684 features: vec!["new_name".to_string(), "new_build_name".to_string()],
685 }),
686 );
687
688 assert_eq!(input, expected);
689 }
690
691 #[test]
693 fn feature_dependency_features() {
694 let optional = make_package_node("optional", vec![("feature", vec![])], None);
695 let build_optional =
696 make_package_node("build_optional", vec![("build_feature", vec![])], None);
697 let mut child = make_package_node(
698 "child",
699 vec![
700 (
701 "one",
702 vec!["optional/feature", "build_optional/build_feature"],
703 ),
704 ("optional", vec!["dep:optional"]),
705 ("build_optional", vec!["dep:build_optional"]),
706 ],
707 Some(Dependency {
708 name: "optional".to_string(),
709 package: RefCell::new(optional.clone()).into(),
710 optional: true,
711 uses_default_features: true,
712 features: vec![],
713 }),
714 );
715 child.build_dependencies.push(Dependency {
716 name: "build_optional".to_string(),
717 package: RefCell::new(build_optional.clone()).into(),
718 optional: true,
719 uses_default_features: true,
720 features: vec![],
721 });
722
723 let mut input = make_package_node(
724 "parent",
725 vec![],
726 Some(Dependency {
727 name: "child".to_string(),
728 package: RefCell::new(child.clone()).into(),
729 optional: false,
730 uses_default_features: true,
731 features: vec!["one".to_string()],
732 }),
733 );
734
735 input.resolve();
736
737 child.dependencies[0].optional = false;
738 child.dependencies[0].features.push("feature".to_string());
739 child.dependencies[0].package = RefCell::new(optional).into();
740 child.dependencies[0]
741 .package
742 .borrow_mut()
743 .enabled_features
744 .extend(["feature".to_string()]);
745 child.build_dependencies[0].optional = false;
746 child.build_dependencies[0]
747 .features
748 .push("build_feature".to_string());
749 child.build_dependencies[0].package = RefCell::new(build_optional).into();
750 child.build_dependencies[0]
751 .package
752 .borrow_mut()
753 .enabled_features
754 .extend(["build_feature".to_string()]);
755 child.enabled_features.extend([
756 "one".to_string(),
757 "optional".to_string(),
758 "build_optional".to_string(),
759 ]);
760
761 let expected = make_package_node(
762 "parent",
763 vec![],
764 Some(Dependency {
765 name: "child".to_string(),
766 package: RefCell::new(child.clone()).into(),
767 optional: false,
768 uses_default_features: true,
769 features: vec!["one".to_string()],
770 }),
771 );
772
773 assert_eq!(input, expected);
774 }
775
776 #[test]
778 fn feature_dependency_defaults() {
779 let optional = make_package_node(
780 "optional",
781 vec![("default", vec!["std"]), ("std", vec![])],
782 None,
783 );
784 let build_optional = make_package_node(
785 "optional",
786 vec![("default", vec!["build"]), ("build", vec![])],
787 None,
788 );
789 let mut child = make_package_node(
790 "child",
791 vec![
792 ("one", vec!["optional", "build_optional"]),
793 ("optional", vec!["dep:optional"]),
794 ("build_optional", vec!["dep:build_optional"]),
795 ],
796 Some(Dependency {
797 name: "optional".to_string(),
798 package: RefCell::new(optional.clone()).into(),
799 optional: true,
800 uses_default_features: true,
801 features: vec![],
802 }),
803 );
804 child.build_dependencies.push(Dependency {
805 name: "build_optional".to_string(),
806 package: RefCell::new(build_optional.clone()).into(),
807 optional: true,
808 uses_default_features: true,
809 features: vec![],
810 });
811
812 let mut input = make_package_node(
813 "parent",
814 vec![],
815 Some(Dependency {
816 name: "child".to_string(),
817 package: RefCell::new(child.clone()).into(),
818 optional: false,
819 uses_default_features: true,
820 features: vec!["one".to_string()],
821 }),
822 );
823
824 input.resolve();
825
826 child.dependencies[0].optional = false;
827 child.dependencies[0].package = RefCell::new(optional).into();
828 child.dependencies[0]
829 .package
830 .borrow_mut()
831 .enabled_features
832 .extend(["std".to_string(), "default".to_string()]);
833 child.build_dependencies[0].optional = false;
834 child.build_dependencies[0].package = RefCell::new(build_optional).into();
835 child.build_dependencies[0]
836 .package
837 .borrow_mut()
838 .enabled_features
839 .extend(["build".to_string(), "default".to_string()]);
840 child.enabled_features.extend([
841 "one".to_string(),
842 "optional".to_string(),
843 "build_optional".to_string(),
844 ]);
845
846 let expected = make_package_node(
847 "parent",
848 vec![],
849 Some(Dependency {
850 name: "child".to_string(),
851 package: RefCell::new(child.clone()).into(),
852 optional: false,
853 uses_default_features: true,
854 features: vec!["one".to_string()],
855 }),
856 );
857
858 assert_eq!(input, expected);
859 }
860
861 #[test]
863 fn feature_dependency_no_defaults() {
864 let optional = make_package_node(
865 "optional",
866 vec![("default", vec!["std"]), ("std", vec![])],
867 None,
868 );
869 let build_optional = make_package_node(
870 "build_optional",
871 vec![("default", vec!["build"]), ("build", vec![])],
872 None,
873 );
874 let mut child = make_package_node(
875 "child",
876 vec![
877 ("one", vec!["optional", "build_optional"]),
878 ("optional", vec!["dep:optional"]),
879 ("build_optional", vec!["dep:build_optional"]),
880 ],
881 Some(Dependency {
882 name: "optional".to_string(),
883 package: RefCell::new(optional.clone()).into(),
884 optional: true,
885 uses_default_features: false,
886 features: vec![],
887 }),
888 );
889 child.build_dependencies.push(Dependency {
890 name: "build_optional".to_string(),
891 package: RefCell::new(build_optional.clone()).into(),
892 optional: true,
893 uses_default_features: false,
894 features: vec![],
895 });
896
897 let mut input = make_package_node(
898 "parent",
899 vec![],
900 Some(Dependency {
901 name: "child".to_string(),
902 package: RefCell::new(child.clone()).into(),
903 optional: false,
904 uses_default_features: true,
905 features: vec!["one".to_string()],
906 }),
907 );
908
909 input.resolve();
910
911 child.dependencies[0].optional = false;
912 child.dependencies[0].package = RefCell::new(optional).into();
913 child.build_dependencies[0].optional = false;
914 child.build_dependencies[0].package = RefCell::new(build_optional).into();
915 child.enabled_features.extend([
916 "one".to_string(),
917 "optional".to_string(),
918 "build_optional".to_string(),
919 ]);
920
921 let expected = make_package_node(
922 "parent",
923 vec![],
924 Some(Dependency {
925 name: "child".to_string(),
926 package: RefCell::new(child.clone()).into(),
927 optional: false,
928 uses_default_features: true,
929 features: vec!["one".to_string()],
930 }),
931 );
932
933 assert_eq!(input, expected);
934 }
935
936 #[test]
938 fn feature_on_optional_dependency() {
939 let optional = make_package_node(
940 "optional",
941 vec![("disabled", vec![]), ("enabled", vec![])],
942 None,
943 );
944 let build_optional = make_package_node(
945 "build_optional",
946 vec![("build_disabled", vec![]), ("build_enabled", vec![])],
947 None,
948 );
949 let mut child = make_package_node(
950 "child",
951 vec![
952 ("optional", vec!["dep:optional"]),
953 ("build_optional", vec!["dep:build_optional"]),
954 (
955 "hi",
956 vec!["optional?/enabled", "build_optional?/build_enabled"],
957 ),
958 ],
959 Some(Dependency {
960 name: "optional".to_string(),
961 package: RefCell::new(optional.clone()).into(),
962 optional: true,
963 uses_default_features: false,
964 features: vec![],
965 }),
966 );
967 child.build_dependencies.push(Dependency {
968 name: "build_optional".to_string(),
969 package: RefCell::new(build_optional.clone()).into(),
970 optional: true,
971 uses_default_features: false,
972 features: vec![],
973 });
974
975 let mut input = make_package_node(
976 "parent",
977 vec![],
978 Some(Dependency {
979 name: "child".to_string(),
980 package: RefCell::new(child.clone()).into(),
981 optional: false,
982 uses_default_features: true,
983 features: vec![
984 "optional".to_string(),
985 "build_optional".to_string(),
986 "hi".to_string(),
987 ],
988 }),
989 );
990
991 input.resolve();
992
993 child.dependencies[0].optional = false;
994 child.dependencies[0].package = RefCell::new(optional).into();
995 child.dependencies[0]
996 .package
997 .borrow_mut()
998 .enabled_features
999 .extend(["enabled".to_string()]);
1000 child.dependencies[0].features = vec!["enabled".to_string()];
1001 child.build_dependencies[0].optional = false;
1002 child.build_dependencies[0].package = RefCell::new(build_optional).into();
1003 child.build_dependencies[0]
1004 .package
1005 .borrow_mut()
1006 .enabled_features
1007 .extend(["build_enabled".to_string()]);
1008 child.build_dependencies[0].features = vec!["build_enabled".to_string()];
1009 child.enabled_features.extend([
1010 "optional".to_string(),
1011 "build_optional".to_string(),
1012 "hi".to_string(),
1013 ]);
1014
1015 let expected = make_package_node(
1016 "parent",
1017 vec![],
1018 Some(Dependency {
1019 name: "child".to_string(),
1020 package: RefCell::new(child.clone()).into(),
1021 optional: false,
1022 uses_default_features: true,
1023 features: vec![
1024 "optional".to_string(),
1025 "build_optional".to_string(),
1026 "hi".to_string(),
1027 ],
1028 }),
1029 );
1030
1031 assert_eq!(input, expected);
1032 }
1033
1034 #[test]
1051 fn no_default_correctly() {
1052 let mut child = make_package_node(
1053 "child",
1054 vec![("default", vec!["std"]), ("other", vec!["who"])],
1055 None,
1056 );
1057 let child_rc = RefCell::new(child.clone()).into();
1058
1059 let layer1_1 = make_package_node(
1060 "layer1_1",
1061 vec![],
1062 Some(Dependency {
1063 name: "child".to_string(),
1064 package: Rc::clone(&child_rc),
1065 optional: false,
1066 uses_default_features: true,
1067 features: vec!["other".to_string()],
1068 }),
1069 );
1070
1071 let layer1_2 = make_package_node(
1072 "layer1_2",
1073 vec![],
1074 Some(Dependency {
1075 name: "child".to_string(),
1076 package: Rc::clone(&child_rc),
1077 optional: false,
1078 uses_default_features: false,
1079 features: vec!["other".to_string()],
1080 }),
1081 );
1082
1083 let mut input = make_package_node(
1084 "parent",
1085 vec![],
1086 Some(Dependency {
1087 name: "layer1_1".to_string(),
1088 package: RefCell::new(layer1_1).into(),
1089 optional: false,
1090 uses_default_features: true,
1091 features: vec![],
1092 }),
1093 );
1094 input.dependencies.push(Dependency {
1095 name: "layer1_2".to_string(),
1096 package: RefCell::new(layer1_2).into(),
1097 optional: false,
1098 uses_default_features: true,
1099 features: vec![],
1100 });
1101
1102 input.resolve();
1103
1104 child.enabled_features.extend([
1105 "std".to_string(),
1106 "default".to_string(),
1107 "other".to_string(),
1108 "who".to_string(),
1109 ]);
1110
1111 let child_rc = RefCell::new(child).into();
1112
1113 let layer1_1 = make_package_node(
1114 "layer1_1",
1115 vec![],
1116 Some(Dependency {
1117 name: "child".to_string(),
1118 package: Rc::clone(&child_rc),
1119 optional: false,
1120 uses_default_features: true,
1121 features: vec!["other".to_string()],
1122 }),
1123 );
1124
1125 let layer1_2 = make_package_node(
1126 "layer1_2",
1127 vec![],
1128 Some(Dependency {
1129 name: "child".to_string(),
1130 package: Rc::clone(&child_rc),
1131 optional: false,
1132 uses_default_features: false,
1133 features: vec!["other".to_string()],
1134 }),
1135 );
1136
1137 let mut expected = make_package_node(
1138 "parent",
1139 vec![],
1140 Some(Dependency {
1141 name: "layer1_1".to_string(),
1142 package: RefCell::new(layer1_1).into(),
1143 optional: false,
1144 uses_default_features: true,
1145 features: vec![],
1146 }),
1147 );
1148 expected.dependencies.push(Dependency {
1149 name: "layer1_2".to_string(),
1150 package: RefCell::new(layer1_2).into(),
1151 optional: false,
1152 uses_default_features: true,
1153 features: vec![],
1154 });
1155
1156 assert_eq!(input, expected);
1157 }
1158}