diff --git a/examples/test_layout.rs b/examples/test_layout.rs index fec1284f..e2f0dc25 100644 --- a/examples/test_layout.rs +++ b/examples/test_layout.rs @@ -1,77 +1,10 @@ extern crate rs; -extern crate xkbcommon; +use rs::tests::check_builtin_layout; use std::env; -use rs::data::Layout; -use xkbcommon::xkb; - -use rs::util::WarningHandler; - -pub struct CountAndPrint(u32); - -impl WarningHandler for CountAndPrint { - fn handle(&mut self, warning: &str) { - self.0 = self.0 + 1; - println!("{}", warning); - } -} - -impl CountAndPrint { - fn new() -> CountAndPrint { - CountAndPrint(0) - } -} - -fn check_layout(name: &str) { - let handler = CountAndPrint::new(); - let layout = Layout::from_resource(name).expect("Invalid layout file"); - let (layout, handler) = layout.build(handler); - - if handler.0 > 0 { - println!("{} mistakes in layout", handler.0) - } - - let layout = layout.expect("layout broken"); - - let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); - - let keymap_str = layout.keymap_str - .clone() - .into_string().expect("Failed to decode keymap string"); - - let keymap = xkb::Keymap::new_from_string( - &context, - keymap_str.clone(), - xkb::KEYMAP_FORMAT_TEXT_V1, - xkb::KEYMAP_COMPILE_NO_FLAGS, - ).expect("Failed to create keymap"); - - let state = xkb::State::new(&keymap); - - // "Press" each button with keysyms - for view in layout.views.values() { - for row in &view.rows { - for button in &row.buttons { - let keystate = button.state.borrow(); - for keycode in &keystate.keycodes { - match state.key_get_one_sym(*keycode) { - xkb::KEY_NoSymbol => { - eprintln!("{}", keymap_str); - panic!("Keysym {} on key {:?} can't be resolved", keycode, button.name); - }, - _ => {}, - } - } - } - } - } - - if handler.0 > 0 { - panic!("Layout contains mistakes"); - } -} - fn main() -> () { - check_layout(env::args().nth(1).expect("No argument given").as_str()); + check_builtin_layout( + env::args().nth(1).expect("No argument given").as_str() + ); } diff --git a/src/bin/test_layout.rs b/src/bin/test_layout.rs new file mode 100644 index 00000000..3ec5f366 --- /dev/null +++ b/src/bin/test_layout.rs @@ -0,0 +1,8 @@ +extern crate rs; + +use rs::tests::check_layout_file; +use std::env; + +fn main() -> () { + check_layout_file(env::args().nth(1).expect("No argument given").as_str()); +} diff --git a/src/data.rs b/src/data.rs index 541fc2d9..f7ca6865 100644 --- a/src/data.rs +++ b/src/data.rs @@ -305,7 +305,7 @@ impl Layout { .map_err(LoadError::BadResource) } - fn from_file(path: PathBuf) -> Result { + pub fn from_file(path: PathBuf) -> Result { let infile = BufReader::new( fs::OpenOptions::new() .read(true) diff --git a/src/lib.rs b/src/lib.rs index 54fc66b7..d1b7f1b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,5 +24,6 @@ mod outputs; mod popover; mod resources; mod submission; +pub mod tests; pub mod util; mod xdg; diff --git a/src/meson.build b/src/meson.build index e1a98ab9..525fba06 100644 --- a/src/meson.build +++ b/src/meson.build @@ -58,7 +58,7 @@ rslibs = custom_target( output: ['librs.a'], install: false, console: true, - command: [cargo_script, '@OUTPUT@', 'build'] + command: [cargo_script, '@OUTPUT@', 'build', '--lib'] ) build_rstests = custom_target( @@ -124,3 +124,13 @@ squeekboard = executable('squeekboard-real', '-DEEKBOARD_COMPILATION=1', '-DEEK_COMPILATION=1'], ) + +test_layout = custom_target('squeekboard_test_layout', + build_by_default: true, + # meson doesn't track all inputs, cargo does + build_always_stale: true, + output: ['test_layout'], + console: true, + command: [cargo_script, '@OUTPUT@', 'build', '--bin', 'test_layout'], + install_dir: bindir, +) diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 00000000..19922fe7 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,78 @@ +/*! Testing functionality */ + +use ::data::Layout; +use xkbcommon::xkb; + +use ::util::WarningHandler; + + +pub struct CountAndPrint(u32); + +impl WarningHandler for CountAndPrint { + fn handle(&mut self, warning: &str) { + self.0 = self.0 + 1; + println!("{}", warning); + } +} + +impl CountAndPrint { + fn new() -> CountAndPrint { + CountAndPrint(0) + } +} + +pub fn check_builtin_layout(name: &str) { + check_layout(Layout::from_resource(name).expect("Invalid layout data")) +} + +pub fn check_layout_file(path: &str) { + check_layout(Layout::from_file(path.into()).expect("Invalid layout file")) +} + +fn check_layout(layout: Layout) { + let handler = CountAndPrint::new(); + let (layout, handler) = layout.build(handler); + + if handler.0 > 0 { + println!("{} mistakes in layout", handler.0) + } + + let layout = layout.expect("layout broken"); + + let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); + + let keymap_str = layout.keymap_str + .clone() + .into_string().expect("Failed to decode keymap string"); + + let keymap = xkb::Keymap::new_from_string( + &context, + keymap_str.clone(), + xkb::KEYMAP_FORMAT_TEXT_V1, + xkb::KEYMAP_COMPILE_NO_FLAGS, + ).expect("Failed to create keymap"); + + let state = xkb::State::new(&keymap); + + // "Press" each button with keysyms + for view in layout.views.values() { + for row in &view.rows { + for button in &row.buttons { + let keystate = button.state.borrow(); + for keycode in &keystate.keycodes { + match state.key_get_one_sym(*keycode) { + xkb::KEY_NoSymbol => { + eprintln!("{}", keymap_str); + panic!("Keysym {} on key {:?} can't be resolved", keycode, button.name); + }, + _ => {}, + } + } + } + } + } + + if handler.0 > 0 { + panic!("Layout contains mistakes"); + } +}