0018-wasm-康威生命游戏
环境
- Time 2022-05-17
- Rust 1.60.0
- Node 12.22.5
- wasm-pack 0.10.2
前言
说明
参考:https://rustwasm.github.io/docs/book/game-of-life/testing.html
目标
在上一节的基础上进行。对 wasm_bindgen
编写测试。
增加测试支持方法
为了便于测试,增加两个辅助方法。
pub fn get_cells(&self) -> &[u32] {
self.cells.as_slice()
}
pub fn set_cells(&mut self, cells: &[(u32, u32)]) {
(0..self.cells.len()).for_each(|i| self.cells.set(i, false));
for (row, col) in cells.iter().cloned() {
let idx = self.get_index(row, col);
self.cells.set(idx, true);
}
}
测试辅助方法
测试方法编写到根目录下的 tests
目录,新建一个 web.rs 文件。
pub fn input_spaceship() -> Universe {
let mut universe = Universe::new(6, 6);
universe.set_cells(&[(1, 2), (2, 3), (3, 1), (3, 2), (3, 3)]);
universe
}
pub fn expected_spaceship() -> Universe {
let mut universe = Universe::new(6, 6);
universe.set_cells(&[(2, 1), (2, 3), (3, 2), (3, 3), (4, 2)]);
universe
}
测试
#[wasm_bindgen_test]
pub fn test_tick() {
let mut input_universe = input_spaceship();
let expected_universe = expected_spaceship();
input_universe.tick();
assert_eq!(input_universe.get_cells(), expected_universe.get_cells());
}
运行测试
C:\Users\jiangbo\workspace\rust\game>wasm-pack test --node
[INFO]: Checking for the Wasm target...
Compiling game v0.1.0 (C:\Users\jiangbo\workspace\rust\game)
Finished dev [unoptimized + debuginfo] target(s) in 1.39s
[INFO]: Installing wasm-bindgen...
Finished test [unoptimized + debuginfo] target(s) in 0.06s
Running unittests (target\wasm32-unknown-unknown\debug\deps\game-e9cd8d7e6b5cae9c.wasm)
no tests to run!
Running unittests (target\wasm32-unknown-unknown\debug\deps\game-ecc71d555c8b84bd.wasm)
no tests to run!
Running tests\web.rs (target\wasm32-unknown-unknown\debug\deps\web-512684fe9cca97db.wasm)
Set timeout to 20 seconds...
running 1 test
test web::test_tick ... ok
test result: ok. 1 passed; 0 failed; 0 ignored
总结
对康威生命游戏编写了测试代码,针对 wasm_bindgen
进行测试。
附录
lib.rs
mod utils;
use fixedbitset::FixedBitSet;
use js_sys::Math;
use wasm_bindgen::prelude::wasm_bindgen;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub struct Universe {
width: u32,
height: u32,
cells: FixedBitSet,
}
impl Universe {
fn get_index(&self, row: u32, column: u32) -> usize {
(row * self.width + column) as usize
}
fn live_neighbor_count(&self, row: u32, column: u32) -> u8 {
let mut count = 0;
for delta_row in [self.height - 1, 0, 1] {
for delta_col in [self.width - 1, 0, 1] {
if delta_row == 0 && delta_col == 0 {
continue;
}
let neighbor_row = (row + delta_row) % self.height;
let neighbor_col = (column + delta_col) % self.width;
let idx = self.get_index(neighbor_row, neighbor_col);
count += self.cells[idx] as u8;
}
}
count
}
pub fn get_cells(&self) -> &[u32] {
self.cells.as_slice()
}
pub fn set_cells(&mut self, cells: &[(u32, u32)]) {
(0..self.cells.len()).for_each(|i| self.cells.set(i, false));
for (row, col) in cells.iter().cloned() {
let idx = self.get_index(row, col);
self.cells.set(idx, true);
}
}
}
#[wasm_bindgen]
impl Universe {
pub fn tick(&mut self) {
let mut next = self.cells.clone();
for row in 0..self.height {
for col in 0..self.width {
let idx = self.get_index(row, col);
let cell = self.cells[idx];
let live_neighbors = self.live_neighbor_count(row, col);
let next_cell = match (cell, live_neighbors) {
(true, x) if x < 2 || x > 3 => false,
(true, 2) | (true, 3) | (false, 3) => true,
(otherwise, _) => otherwise,
};
next.set(idx, next_cell);
}
}
self.cells = next;
}
pub fn cells(&self) -> *const u32 {
self.cells.as_slice().as_ptr()
}
pub fn new(width: u32, height: u32) -> Universe {
let size = (width * height) as usize;
let mut cells = FixedBitSet::with_capacity(size);
(0..size).for_each(|i| cells.set(i, Math::random() < 0.5));
Universe {
width,
height,
cells,
}
}
}
web.rs
use game::Universe;
use wasm_bindgen_test::wasm_bindgen_test;
pub fn input_spaceship() -> Universe {
let mut universe = Universe::new(6, 6);
universe.set_cells(&[(1, 2), (2, 3), (3, 1), (3, 2), (3, 3)]);
universe
}
pub fn expected_spaceship() -> Universe {
let mut universe = Universe::new(6, 6);
universe.set_cells(&[(2, 1), (2, 3), (3, 2), (3, 3), (4, 2)]);
universe
}
#[wasm_bindgen_test]
pub fn test_tick() {
let mut input_universe = input_spaceship();
let expected_universe = expected_spaceship();
input_universe.tick();
assert_eq!(input_universe.get_cells(), expected_universe.get_cells());
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!