浏览代码

Merge pull request #696 from DioxusLabs/jk/add-miri-to-ci

chore: add miri to CI
Jon Kelley 2 年之前
父节点
当前提交
ab039fd11b

+ 123 - 0
.github/workflows/miri.yml

@@ -0,0 +1,123 @@
+name: Miri Tests
+
+on:
+  push:
+    # Run in PRs and for bors, but not on master.
+    branches:
+      - 'auto'
+      - 'try'
+  pull_request:
+    branches:
+      - 'master'
+  schedule:
+    - cron: '6 6 * * *' # At 6:06 UTC every day.
+
+env:
+  CARGO_UNSTABLE_SPARSE_REGISTRY: 'true'
+  RUSTFLAGS: -Dwarnings
+  RUST_BACKTRACE: 1
+  # Change to specific Rust release to pin
+  rust_stable: stable
+  rust_nightly: nightly-2022-11-03
+  rust_clippy: 1.65.0
+  # When updating this, also update:
+  # - README.md
+  # - tokio/README.md
+  # - CONTRIBUTING.md
+  # - tokio/Cargo.toml
+  # - tokio-util/Cargo.toml
+  # - tokio-test/Cargo.toml
+  # - tokio-stream/Cargo.toml
+  # rust_min: 1.49.0
+
+
+
+jobs:
+  test:
+    runs-on: ${{ matrix.os }}
+    env:
+      RUST_BACKTRACE: 1
+      HOST_TARGET: ${{ matrix.host_target }}
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - os: ubuntu-latest
+            host_target: x86_64-unknown-linux-gnu
+          # - os: macos-latest
+          #   host_target: x86_64-apple-darwin
+          # - os: windows-latest
+          #   host_target: i686-pc-windows-msvc
+          # - os: windows-latest
+          #   host_target: i686-pc-windows-msvc
+          # - os: windows-latest
+          #   host_target: i686-pc-windows-msvc
+          # - os: windows-latest
+          #   host_target: i686-pc-windows-msvc
+    steps:
+      - name: Set the tag GC interval to 1 on linux
+        if: runner.os == 'Linux'
+        run: echo "MIRIFLAGS=-Zmiri-tag-gc=1" >> $GITHUB_ENV
+
+      - uses: actions/checkout@v3
+      - name: Install Rust ${{ env.rust_nightly }}
+        uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{ env.rust_nightly }}
+          components: miri
+      - uses: Swatinem/rust-cache@v2
+      - name: miri
+        # Many of tests in tokio/tests and doctests use #[tokio::test] or
+        # #[tokio::main] that calls epoll_create1 that Miri does not support.
+        # run: cargo miri test --features full --lib --no-fail-fast
+        run: |
+          cargo miri test --package dioxus-core --test miri_stress  -- --exact --nocapture
+          cargo miri test --package dioxus-native-core --test miri_native  -- --exact --nocapture
+
+        # working-directory: tokio
+        env:
+          #  todo: disable memory leaks ignore
+          MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields -Zmiri-ignore-leaks
+          PROPTEST_CASES: 10
+
+      # Cache the global cargo directory, but NOT the local `target` directory which
+      # we cannot reuse anyway when the nightly changes (and it grows quite large
+      # over time).
+      # - name: Add cache for cargo
+      #   id: cache
+      #   uses: actions/cache@v3
+      #   with:
+      #     path: |
+      #       # Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>.
+      #       ~/.cargo/bin
+      #       ~/.cargo/registry/index
+      #       ~/.cargo/registry/cache
+      #       ~/.cargo/git/db
+      #       # contains package information of crates installed via `cargo install`.
+      #       ~/.cargo/.crates.toml
+      #       ~/.cargo/.crates2.json
+      #     key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+      #     restore-keys: ${{ runner.os }}-cargo
+
+      # - name: Install rustup-toolchain-install-master
+      #   if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+      #   shell: bash
+      #   run: |
+      #     cargo install -f rustup-toolchain-install-master
+      # - name: Install "master" toolchain
+      #   shell: bash
+      #   run: |
+      #     if [[ ${{ github.event_name }} == 'schedule' ]]; then
+      #       echo "Building against latest rustc git version"
+      #       git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
+      #     fi
+      #      toolchain --host ${{ matrix.host_target }}
+      # - name: Show Rust version
+      #   run: |
+      #     rustup show
+      #     rustc -Vv
+      #     cargo -V
+      # - name: Test
+      #   run: |
+      #     MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks" cargo +nightly miri test --package dioxus-core --test miri_stress  -- --exact --nocapture
+      #     MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks" cargo +nightly miri test --package dioxus-native-core --test miri_native  -- --exact --nocapture

+ 1 - 0
packages/core/src/lazynodes.rs

@@ -11,6 +11,7 @@
 //! The logic for this was borrowed from <https://docs.rs/stack_dst/0.6.1/stack_dst/>. Unfortunately, this crate does not
 //! support non-static closures, so we've implemented the core logic of `ValueA` in this module.
 
+#[allow(unused_imports)]
 use smallbox::{smallbox, space::S16, SmallBox};
 
 use crate::{innerlude::VNode, ScopeState};

+ 76 - 0
packages/core/tests/miri_stress.rs

@@ -137,6 +137,82 @@ fn free_works_on_root_hooks() {
     assert_eq!(Rc::strong_count(&ptr), 1);
 }
 
+#[test]
+fn supports_async() {
+    use std::time::Duration;
+    use tokio::time::sleep;
+
+    fn app(cx: Scope) -> Element {
+        let colors = use_state(&cx, || vec!["green", "blue", "red"]);
+        let padding = use_state(&cx, || 10);
+
+        use_effect(&cx, colors, |colors| async move {
+            sleep(Duration::from_millis(1000)).await;
+            colors.with_mut(|colors| colors.reverse());
+        });
+
+        use_effect(&cx, padding, |padding| async move {
+            sleep(Duration::from_millis(10)).await;
+            padding.with_mut(|padding| {
+                if *padding < 65 {
+                    *padding += 1;
+                } else {
+                    *padding = 5;
+                }
+            });
+        });
+
+        let big = colors[0];
+        let mid = colors[1];
+        let small = colors[2];
+
+        cx.render(rsx! {
+            div {
+                background: "{big}",
+                height: "stretch",
+                width: "stretch",
+                padding: "50",
+                label {
+                    "hello",
+                }
+                div {
+                    background: "{mid}",
+                    height: "auto",
+                    width: "stretch",
+                    padding: "{padding}",
+                    label {
+                        "World",
+                    }
+                    div {
+                        background: "{small}",
+                        height: "auto",
+                        width: "stretch",
+                        padding: "20",
+                        label {
+                            "ddddddd",
+                        }
+                    }
+                },
+            }
+        })
+    }
+
+    let rt = tokio::runtime::Builder::new_current_thread()
+        .enable_time()
+        .build()
+        .unwrap();
+
+    rt.block_on(async {
+        let mut dom = VirtualDom::new(app);
+        let _ = dom.rebuild();
+
+        for x in 0..10 {
+            let _ = dom.wait_for_work().await;
+            let edits = dom.render_immediate();
+        }
+    });
+}
+
 // #[test]
 // fn old_props_arent_stale() {
 //     fn app(cx: Scope) -> Element {

+ 2 - 0
packages/native-core/Cargo.toml

@@ -30,3 +30,5 @@ lightningcss = "1.0.0-alpha.39"
 [dev-dependencies]
 rand = "0.8.5"
 dioxus = { path = "../dioxus", version = "^0.3.0" }
+dioxus-native-core-macro = { path = "../native-core-macro" }
+tokio = { version = "*", features = ["full"] }

+ 146 - 0
packages/native-core/tests/miri_native.rs

@@ -0,0 +1,146 @@
+use dioxus::prelude::*;
+use dioxus_native_core::*;
+use dioxus_native_core::{
+    node_ref::{AttributeMask, NodeView},
+    real_dom::RealDom,
+    state::{ParentDepState, State},
+    NodeMask, SendAnyMap,
+};
+use dioxus_native_core_macro::{sorted_str_slice, State};
+use std::{
+    sync::{Arc, Mutex},
+    time::Duration,
+};
+use tokio::time::sleep;
+
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct BlablaState {}
+
+/// Font style are inherited by default if not specified otherwise by some of the supported attributes.
+impl ParentDepState for BlablaState {
+    type Ctx = ();
+    type DepState = (Self,);
+
+    const NODE_MASK: NodeMask =
+        NodeMask::new_with_attrs(AttributeMask::Static(&sorted_str_slice!(["blabla",])));
+
+    fn reduce<'a>(
+        &mut self,
+        _node: NodeView,
+        _parent: Option<(&'a Self,)>,
+        _ctx: &Self::Ctx,
+    ) -> bool {
+        false
+    }
+}
+
+#[derive(Clone, State, Default, Debug)]
+pub struct NodeState {
+    #[parent_dep_state(blabla)]
+    blabla: BlablaState,
+}
+
+mod dioxus_elements {
+    macro_rules! builder_constructors {
+        (
+            $(
+                $(#[$attr:meta])*
+                $name:ident {
+                    $(
+                        $(#[$attr_method:meta])*
+                        $fil:ident: $vil:ident,
+                    )*
+                };
+            )*
+        ) => {
+            $(
+                #[allow(non_camel_case_types)]
+                $(#[$attr])*
+                pub struct $name;
+
+                impl $name {
+                    pub const TAG_NAME: &'static str = stringify!($name);
+                    pub const NAME_SPACE: Option<&'static str> = None;
+
+                    $(
+                        pub const $fil: (&'static str, Option<&'static str>, bool) = (stringify!($fil), None, false);
+                    )*
+                }
+
+                impl GlobalAttributes for $name {}
+            )*
+        }
+    }
+
+    pub trait GlobalAttributes {}
+
+    pub trait SvgAttributes {}
+
+    builder_constructors! {
+        blabla {
+
+        };
+    }
+}
+
+#[test]
+fn native_core_is_okay() {
+    use std::time::Duration;
+
+    fn app(cx: Scope) -> Element {
+        let colors = use_state(&cx, || vec!["green", "blue", "red"]);
+        let padding = use_state(&cx, || 10);
+
+        use_effect(&cx, colors, |colors| async move {
+            sleep(Duration::from_millis(1000)).await;
+            colors.with_mut(|colors| colors.reverse());
+        });
+
+        use_effect(&cx, padding, |padding| async move {
+            sleep(Duration::from_millis(10)).await;
+            padding.with_mut(|padding| {
+                if *padding < 65 {
+                    *padding += 1;
+                } else {
+                    *padding = 5;
+                }
+            });
+        });
+
+        let big = colors[0];
+        let mid = colors[1];
+        let small = colors[2];
+
+        cx.render(rsx! {
+            blabla {}
+        })
+    }
+
+    let rt = tokio::runtime::Builder::new_current_thread()
+        .enable_time()
+        .build()
+        .unwrap();
+
+    rt.block_on(async {
+        let rdom = Arc::new(Mutex::new(RealDom::<NodeState>::new()));
+        let mut dom = VirtualDom::new(app);
+
+        let muts = dom.rebuild();
+        let (to_update, _diff) = rdom.lock().unwrap().apply_mutations(muts);
+
+        let ctx = SendAnyMap::new();
+        let ctx = SendAnyMap::new();
+        rdom.lock().unwrap().update_state(to_update, ctx);
+
+        for x in 0..10 {
+            dom.wait_for_work().await;
+
+            let mutations = dom.render_immediate();
+            let (to_update, _diff) = rdom.lock().unwrap().apply_mutations(mutations);
+
+            let ctx = SendAnyMap::new();
+            let ctx = SendAnyMap::new();
+            rdom.lock().unwrap().update_state(to_update, ctx);
+        }
+    });
+}