miri_stress.rs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. Stress Miri as much as possible.
  3. Prove that we don't leak memory and that our methods are safe.
  4. Specifically:
  5. - [ ] VirtualDom drops memory safely
  6. - [ ] Borrowed components don't expose invalid pointers
  7. - [ ] Async isn't busted
  8. */
  9. use dioxus::{prelude::*, DomEdit, ScopeId};
  10. use dioxus_core as dioxus;
  11. use dioxus_core_macro::*;
  12. use dioxus_html as dioxus_elements;
  13. mod test_logging;
  14. use DomEdit::*;
  15. const IS_LOGGING_ENABLED: bool = false;
  16. fn new_dom<P: 'static + Send>(app: Component<P>, props: P) -> VirtualDom {
  17. test_logging::set_up_logging(IS_LOGGING_ENABLED);
  18. VirtualDom::new_with_props(app, props)
  19. }
  20. /// This test ensures that if a component aborts early, it is replaced with a placeholder.
  21. /// In debug, this should also toss a warning.
  22. #[test]
  23. fn test_memory_leak() {
  24. fn app(cx: Scope<()>) -> Element {
  25. let val = cx.use_hook(|_| 0, |f| f);
  26. *val += 1;
  27. if *val == 2 || *val == 4 {
  28. return None;
  29. }
  30. let name = cx.use_hook(|_| String::from("asd"), |f| f);
  31. cx.render(rsx!(
  32. div { "Hello, world!" }
  33. child()
  34. child()
  35. child()
  36. child()
  37. child()
  38. child()
  39. borrowed_child(na: name)
  40. borrowed_child(na: name)
  41. borrowed_child(na: name)
  42. borrowed_child(na: name)
  43. borrowed_child(na: name)
  44. ))
  45. }
  46. fn child(cx: Scope<()>) -> Element {
  47. rsx!(cx, div {
  48. "goodbye world"
  49. })
  50. }
  51. #[derive(Props)]
  52. struct BorrowedProps<'a> {
  53. na: &'a str,
  54. }
  55. fn borrowed_child<'a>(cx: Scope<'a, BorrowedProps<'a>>) -> Element {
  56. rsx!(cx, div {
  57. "goodbye {cx.props.na}"
  58. child()
  59. child()
  60. })
  61. }
  62. let mut dom = new_dom(app, ());
  63. dom.rebuild();
  64. dom.hard_diff(ScopeId(0));
  65. dom.hard_diff(ScopeId(0));
  66. dom.hard_diff(ScopeId(0));
  67. dom.hard_diff(ScopeId(0));
  68. dom.hard_diff(ScopeId(0));
  69. dom.hard_diff(ScopeId(0));
  70. }
  71. #[test]
  72. fn memo_works_properly() {
  73. fn app(cx: Scope<()>) -> Element {
  74. let val = cx.use_hook(|_| 0, |f| f);
  75. *val += 1;
  76. if *val == 2 || *val == 4 {
  77. return None;
  78. }
  79. let name = cx.use_hook(|_| String::from("asd"), |f| f);
  80. cx.render(rsx!(
  81. div { "Hello, world!" }
  82. child(na: "asd".to_string())
  83. ))
  84. }
  85. #[derive(PartialEq, Props)]
  86. struct ChildProps {
  87. na: String,
  88. }
  89. fn child(cx: Scope<ChildProps>) -> Element {
  90. rsx!(cx, div {
  91. "goodbye world"
  92. })
  93. }
  94. let mut dom = new_dom(app, ());
  95. dom.rebuild();
  96. dom.hard_diff(ScopeId(0));
  97. dom.hard_diff(ScopeId(0));
  98. dom.hard_diff(ScopeId(0));
  99. dom.hard_diff(ScopeId(0));
  100. dom.hard_diff(ScopeId(0));
  101. }