Skip to content

Commit

Permalink
feat(ribir): 🎸 add macro example_framework to help write example an…
Browse files Browse the repository at this point in the history
…d its test
  • Loading branch information
M-Adoo committed Jun 13, 2023
1 parent 4afe10c commit 745f2d0
Show file tree
Hide file tree
Showing 55 changed files with 368 additions and 123 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/alpha-release.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '0 2 * * 2' # runs every tuesday at 00:00
- cron: "0 2 * * 2" # runs every tuesday at 00:00
name: "release weekly alpha version"
jobs:
release:
Expand Down Expand Up @@ -30,10 +30,14 @@ jobs:
with:
command: login
args: ${{ secrets.CRATE_RELEASE_TOKEN }}
- name: git config
run: |
git config --global user.email "[email protected]"
git config --global user.name "Adoo"
- name: Run cargo release
if: ${{ env.NEW_COMMIT_COUNT > 0 }}
uses: actions-rs/cargo@v1
with:
command: release
args: alpha --execute --no-confirm

12 changes: 5 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,8 @@ jobs:
- name: cargo check
run: cargo check
test:
name: Test Suite
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
name: Test Suite / ubuntu-latest
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v3
Expand All @@ -44,6 +41,7 @@ jobs:
toolchain: nightly-2023-02-01
- uses: Swatinem/rust-cache@v2
- run: cargo test --no-default-features
features-test:
needs: test
self-host:
name: Test Suite
needs: lint
uses: RibirX/share-workflows/.github/workflows/ribir-win-image-tests.yaml@main
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[workspace]
exclude = [
"examples/attachments",
]
members = [
"core",
"gpu",
Expand All @@ -13,6 +16,7 @@ members = [
"geom",
"tests",
"dev-helper",
"examples/*",
]
resolver = "2"

Expand All @@ -37,6 +41,7 @@ version = "0.0.1-alpha.1"
[workspace.dependencies]
Inflector = "0.11.4"
ahash = "0.8.3"
arboard = "3.2.0"
bitflags = "2.0.0"
blake3 = "1.3.3"
colored = "2.0.0"
Expand Down Expand Up @@ -66,7 +71,7 @@ raw-window-handle = "0.5.0"
rayon = "1.5.1"
rctree = "0.5.0"
rustybuzz = "0.7.0"
rxrust = {version = "1.0.0-beta.3", default-features = false, features = ["futures-scheduler"]}
rxrust = {version = "1.0.0-beta.4", default-features = false, features = ["futures-scheduler"]}
scoped_threadpool = "0.1.9"
serde = "1.0"
serde_json = "1.0.82"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Ribir is [MIT licensed](./LICENSE)

[Flutter]: https://flutter.dev/
[QML]: https://doc.qt.io/qt-6/qtqml-index.html
[Examples]: ./ribir/examples/
[Examples]: ./examples/
[Documents]: https://ribir.org/docs/introduction
[Wgpu]: https://github.com/gfx-rs/wgpu

17 changes: 9 additions & 8 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,29 @@ version.workspace = true

[dependencies]
ahash.workspace = true
arboard.workspace = true
bitflags.workspace = true
blake3 = {workspace = true, features = ["rayon"]}
futures.workspace = true
indextree.workspace = true
lazy_static.workspace = true
log.workspace = true
lyon_geom.workspace = true
ribir_algo = {path = "../algo", version = "0.0.1-alpha.1" }
ribir_geom = {path = "../geom", version = "0.0.1-alpha.1" }
ribir_macros = {path = "../macros", version = "0.0.1-alpha.1" }
ribir_painter = {path = "../painter", version = "0.0.1-alpha.1" }
ribir_text = {path = "../text", version = "0.0.1-alpha.1" }
once_cell.workspace = true
pin-project-lite.workspace = true
ribir_algo = {path = "../algo", version = "0.0.1-alpha.1"}
ribir_geom = {path = "../geom", version = "0.0.1-alpha.1"}
ribir_macros = {path = "../macros", version = "0.0.1-alpha.1"}
ribir_painter = {path = "../painter", version = "0.0.1-alpha.1"}
ribir_text = {path = "../text", version = "0.0.1-alpha.1"}
rxrust.workspace = true
smallvec.workspace = true
winit.workspace = true
arboard = "3.2.0"
pin-project-lite.workspace = true

[dev-dependencies]
colored.workspace = true
paste.workspace = true
ribir_dev_helper = {path = "../dev-helper", version = "0.0.1-alpha.1" }
ribir_dev_helper = {path = "../dev-helper", version = "0.0.1-alpha.1"}

[features]
png = ["ribir_painter/png"]
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod dynamic_widget;
pub mod enum_widget;
pub mod events;
pub mod ticker;
pub mod timer;
pub mod widget;
pub mod widget_children;
pub mod window;
Expand Down
14 changes: 14 additions & 0 deletions core/src/test_helper.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::timer::Timer;
use std::sync::atomic::{AtomicU64, Ordering};

use crate::{
Expand All @@ -16,6 +17,8 @@ pub struct TestWindow(Window);
impl TestWindow {
/// Create a 1024x1024 window for test
pub fn new<M: ImplMarker>(root: impl IntoWidget<M>) -> Self {
let _ = NEW_TIMER_FN.set(Timer::new_timer_future);

Self(Window::new(
root.into_widget(),
Box::new(TestShellWindow::new(None)),
Expand All @@ -24,6 +27,8 @@ impl TestWindow {
}

pub fn new_with_size<M: ImplMarker>(root: impl IntoWidget<M>, size: Size) -> Self {
let _ = NEW_TIMER_FN.set(Timer::new_timer_future);

Self(Window::new(
root.into_widget(),
Box::new(TestShellWindow::new(Some(size))),
Expand All @@ -36,6 +41,8 @@ impl TestWindow {
size: Size,
ctx: AppContext,
) -> Self {
let _ = NEW_TIMER_FN.set(Timer::new_timer_future);

Self(Window::new(
root.into_widget(),
Box::new(TestShellWindow::new(Some(size))),
Expand Down Expand Up @@ -71,6 +78,13 @@ impl TestWindow {
.last_frame
.take()
}

pub fn draw_frame(&mut self) {
// Test window not have a eventloop, manually wake-up every frame.
Timer::wake_timeout_futures();

self.0.draw_frame();
}
}

impl std::ops::Deref for TestWindow {
Expand Down
22 changes: 11 additions & 11 deletions ribir/src/timer.rs → core/src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,31 @@ impl TimeReactor {
pub(crate) static TIME_REACTOR: Lazy<Mutex<TimeReactor>> =
Lazy::new(|| Mutex::new(TimeReactor::default()));

pub fn wake_timeout_futures() {
let notifies = TIME_REACTOR.lock().unwrap().timeout_wakers(Instant::now());
notifies.for_each(|waker| waker.wake());
}

pub(crate) fn recently_timeout() -> Option<Instant> {
TIME_REACTOR.lock().unwrap().recently_timeout()
}
pub struct Timer {
id: Option<usize>,
when: Instant,
}

impl Timer {
pub fn new(when: Instant) -> Self { Self { id: None, when } }

pub fn reset(&mut self, timer: Instant) {
if let Some(id) = self.id.take() {
TIME_REACTOR.lock().unwrap().remove_timer(self.when, id)
}
self.when = timer;
}
}

pub fn new_timer(dur: Duration) -> BoxFuture<'static, ()> {
Box::pin(Timer::new(Instant::now() + dur))
pub fn recently_timeout() -> Option<Instant> { TIME_REACTOR.lock().unwrap().recently_timeout() }

pub fn new_timer_future(dur: Duration) -> BoxFuture<'static, ()> {
Box::pin(Timer::new(Instant::now() + dur))
}

pub fn wake_timeout_futures() {
let notifies = TIME_REACTOR.lock().unwrap().timeout_wakers(Instant::now());
notifies.for_each(|waker| waker.wake());
}
}

impl Future for Timer {
Expand Down
50 changes: 50 additions & 0 deletions dev-helper/src/example_framework.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/// Macro help to write an example. This macro accepts a function that returns a
/// widget as the root of the application, you can specify the window size by
/// `wnd_size = { size }`. It will generate codes for you:
///
/// - the `main` function of startup application
/// - use the `wnd_size` you provide or a default size `400x600`
/// - use the package name in `Cargo.toml` as the window title.
/// - generate an image test for the root widget, to ensure every modification
/// is work for your example.
/// - generate an bench test for the root widget, so we can continue to track
/// the performance of the example.
///
/// We may add in the future:
///
/// - report the bundle binary size of this example.
/// - report the startup time of the example.
/// - report the memory and gpu memory used in this example.
/// - report how many frames it can render in one second when vsync-off.

#[macro_export]
macro_rules! example_framework {
(
$widget_fn: ident $(,)?
) => {
example_framework!($widget_fn, wnd_size = Size::new(400., 600.));
};
(
$widget_fn: ident,
wnd_size = $size: expr $(,)?
) => {
#[cfg(test)]
use ribir::core::test_helper::*;
#[cfg(test)]
extern crate test;
#[cfg(test)]
use ribir::material as ribir_material;
#[cfg(test)]
use test::Bencher;

widget_bench!($widget_fn, wnd_size = $size);
widget_image_test!($widget_fn, wnd_size = $size,);

fn main() {
let mut app = App::new(material::purple::light());
let name = env!("CARGO_PKG_NAME");
app.new_window($widget_fn(), Some($size)).set_title(name);
app.exec()
}
};
}
1 change: 1 addition & 0 deletions dev-helper/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod painter_backend_eq_image_test;
pub use painter_backend_eq_image_test::*;
mod example_framework;
mod unit_test_describe;
mod widget_test;
2 changes: 1 addition & 1 deletion dev-helper/src/painter_backend_eq_image_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub fn assert_texture_eq_png(img: PixelImage, file_path: &std::path::Path) {
)
.unwrap();

const TOLERANCE: f64 = 0.000001;
const TOLERANCE: f64 = 0.000002;
let (v, _) = dssim.compare(&expected, dissim_mig);
let v: f64 = v.into();

Expand Down
7 changes: 1 addition & 6 deletions dev-helper/src/widget_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,7 @@ macro_rules! widget_bench {
let ctx = AppContext::default();
b.iter(move || {
let mut wnd = TestWindow::new_with_ctx($widget_fn(), $size, ctx.clone());
loop{
if !wnd.need_draw() {
break;
}
wnd.layout();
}
wnd.draw_frame();
});
}
}
Expand Down
File renamed without changes
11 changes: 11 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Ribir Examples

All the examples in this folder use the macro `example_framework!` to startup, the examples will generate tests and benchmarks for the example to ensure every modification work for those examples.

Run examples:

```
cargo run -p storybook --features="wgpu"
```

Remember add `--features="wgpu"` to use `wgpu` painter-backend to render, we not enable it as default.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
21 changes: 21 additions & 0 deletions examples/counter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
authors.workspace = true
categories.workspace = true
description.workspace = true
documentation.workspace = true
edition.workspace = true
homepage.workspace = true
keywords.workspace = true
license.workspace = true
name = "counter"
publish = false
version.workspace = true

[dependencies]
paste.workspace = true
# we disable `default-features`, because we want more control over testing.
ribir = {path = "../../ribir", features = ["material", "widgets"], default-features = false}
ribir_dev_helper = {path = "../../dev-helper"}

[features]
wgpu = ["ribir/wgpu"]
9 changes: 9 additions & 0 deletions examples/counter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Counter

Exampling how to increase count or decrease count via buttons.


You can run with:
```
cargo run --p counter
```
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use ribir::prelude::*;
fn main() {
App::run(widget! {

pub fn counter() -> Widget {
widget! {
states { cnt: Stateful::new(0) }
Column {
h_align: HAlign::Center,
Expand All @@ -9,5 +10,5 @@ fn main() {
H1 { text: cnt.to_string() }
FilledButton { on_tap: move |_| *cnt += -1, Label::new("Sub") }
}
});
}
}
8 changes: 8 additions & 0 deletions examples/counter/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![feature(test)]

mod counter;
use counter::counter;
use ribir::prelude::*;
use ribir_dev_helper::*;

example_framework!(counter);
21 changes: 21 additions & 0 deletions examples/greet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
authors.workspace = true
categories.workspace = true
description.workspace = true
documentation.workspace = true
edition.workspace = true
homepage.workspace = true
keywords.workspace = true
license.workspace = true
name = "greet"
publish = false
version.workspace = true

[dependencies]
paste.workspace = true
# we disable `default-features`, because we want more control over testing.
ribir = {path = "../../ribir", features = ["material", "widgets"], default-features = false}
ribir_dev_helper = {path = "../../dev-helper"}

[features]
wgpu = ["ribir/wgpu"]
Loading

0 comments on commit 745f2d0

Please sign in to comment.