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());
}
posted @   jiangbo4444  阅读(76)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示