Attending the Chaos Camp 2019 as speaker was quite an experience. I did a talk about Secure Architecture of IoT Devices https://fahrplan.events.ccc.de/camp/2019/Fahrplan/events/10268.html
Category Archives: Rust
UTest Harness for Rust (Setup/Test/Release)
Edit Titel should have been “setup/test/teardown”
The crate test-generator-utest implements a 3-phase utest-harness for Rust. These 3 phases are:
Setup: the setup function must initialize the context; in case the setup-function panics/aborts, the utest is aborted
fn() -> Context
Test: if the setup did return with valud context item, the context-reference is borowed to invoke the test-function
fn( & Context )
Teardown: no matter if the test-function above did panic/abort, the teardown function is invoked to release the context
fn( Context )
No matter of any panic or failing assertion in the second phase (feature testing), the teardown function is invoked. The test will either succeed, or otherwise unwinding a failure in the setup-phase, the test-phase or the teardown-phase.
This crate has been inspired by the post of Eric Opines.
## Usage
Please see the executable example mytests
#[cfg(test)] extern crate test_generator_utest; // demonstrating usage of utest-harness mod testsuite { use std::fs::File; use std::io::prelude::*; use test_generator_utest::utest; // Defining a context structure, storing the resources struct Context<'t> { file: File, name: &'t str } // Setup - Initializing the resources fn setup<'t>(filename: &str) -> Context { // unwrap may panic Context { file: File::create(filename).unwrap(), name: filename } } // Teardown - Releasing the resources fn teardown(context: Context) { let Context { file, name } = context; // drop file resources std::mem::drop(file); // unwrap may panic std::fs::remove_file(name).unwrap(); } // Test - verify feature fn test_write_hello_world(ctx: &Context) { // may panic let mut file = ctx.file.try_clone().unwrap(); // may panic file.write_all(b"Hello, world!\n").unwrap(); // demonstrating assertion assert_eq!(1,1); std::mem::drop(file); } // Test - verify feature fn test_write_hello_europe(ctx: &Context) { // may panic let mut file = ctx.file.try_clone().unwrap(); // may panic file.write_all(b"Hello, Europe!\n").unwrap(); // demonstrating assertion assert_eq!(1,1); std::mem::drop(file); } // Defining Utest formed by setup, test and teardown utest!(hello_world, || setup("/tmp/hello_world.txt"), |ctx_ref| test_write_hello_world(ctx_ref), |ctx|teardown(ctx)); // Defining Utest formed by setup, test and teardown utest!(hello_europe, || setup("/tmp/hello_europe.txt"), test_write_hello_europe, teardown); }
Executing the example code cargo test -p test-generator-example testsuite
the testsuote above will print the following output.
running 2 tests
test testsuite::hello_europe ... ok
test testsuite::hello_world ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 3 filtered out
Please let me know about possibel improvements via github-issues at test-generator-utest
Test-generator v0.3
A new version of test-generator (0.3) has been published. This crate introduces #[test_resources(PATTERN]
and #[bench_resources(PATTERN)]
procedural macro attributes that generates multiple parametrized tests using one body with different resource input parameters. A test is generated for each resource matching the specific resource location pattern.
Rust derive(Default) for enum-types
Rust derive(Default) can be used for structs, implemting the default-instanciation. Sadly it can’t be used for enum-types, as there is no strategy to pick one of the enum-variants as default. The following discussion at Rust Internals hopefully will trigger an RFC to close this feature-gap.
https://internals.rust-lang.org/t/request-derive-enums-default/10576
The Computer Language Benachmarks Game: Rust ranks #1 for n-body
The Computer Language Benchmarks Game is a free software project for comparing how a given subset of simple algorithms can be implemented in various popular programming languages.
I converted the fastest (dating early 2019) n-body C-implementation (#4) to Rust (#7) in a one-to-one fashion, gaining a performance encreasement by factor 1.6 to my own surprise.
The moment writing, the benachmarks are measured on quad-core 2.4Ghz Intel® Q6600® ; dating back to the year 2006. This ancient hardware supports the SSSE3 64bit-SIMD instructions; both implementations are making use them intensively.
The conversion of the implementation from C to Rust was fun and educational; listing just a few:
- The pattern of “static global memory” of C had to be transformed to similar code just based on he Rust ownership model.
- Dealing with memory alignment-directives in Rust
- Using the early, stable SIMD-API of Rust, namely
std::arch::x86_64::*
I must admit that newer test-hardware with support for more advanced AVX-512 SIMD-instructions, would permit to run an even faster Rust-implementation of the n-body task as part of these benchmarks.
Rust crates – frehberg’s annotated catalogue
The base of Rust users and contributors is growing steadily. The amount of libraries (aka crates) at http://crates.io is growing quickly; the overall “noise” is increasing. Some libraries might not be maintained any longer 🙁
This annotated catalogue shall help the Rust-users to find specific, popular, mature Rust crates. This list is WIP (Work In Progress), reflecting my personal shortlist. The ordering in the table top-down doesn’t express any preference.
For more extensive listings, please check out content of https://crates.io (or the categorized search engine https://lib.rs) and corresponding API-docs at https://docs.rs
Other sources of information might be:
- https://github.com/brson/stdx
- https://github.com/rust-unofficial/awesome-rust
- Or various arewe*yet from https://wiki.mozilla.org/Areweyet such as
Name | Description |
---|---|
nom | nom is a parser combinators library written in Rust. Its goal is to provide tools to build safe parsers without compromising the speed or memory consumption. |
pest | pest is a general purpose parser written in Rust with a focus on accessibility, correctness, and performance. It uses parsing expression grammars (or PEG) as input. |
assert_matches | Provides a macro, assert_matches, which tests whether a value matches a given pattern, causing a panic if the match fails. |
bytes | A utility library for working with bytes. |
serde | Serde is a framework for serializing and deserializing Rust data structures efficiently and generically. |
serde_json | Serde JSON serializing and deserializing implementation for Rust. |
tokio | Tokio is an event-driven, non-blocking I/O platform for writing asynchronous applications with the Rust programming language. |
romio | Asynchronous network primitives in Rust. Romio combines the powerful futures abstractions with the nonblocking IO primitives of mio to provide efficient and ergonomic asynchronous IO primitives for the Rust asynchronous networking ecosystem. Whereas Tokio is using stable Rust-features only, Romio may use so called "unstable" Rust-features from nightly releases. |
uom | Units of measurement is a crate that does automatic type-safe zero-cost dimensional analysis. |
mockiato | A strict, yet friendly mocking library for Rust |
proptest | Proptest is a property testing framework (i.e., the QuickCheck family) inspired by the Hypothesis framework for Python. It allows to test that certain properties of your code hold for arbitrary inputs, and if a failure is found, automatically finds the minimal test case to reproduce the problem. |
test-case-derive | This crate provides #[test_case] procedural macro attribute that generates multiple parametrized tests using one body with different input parameters. |
env_logger | Implements a logger that can be configured via environment variables. env_logger makes sense when used in executables (binary projects). Libraries should use the log crate instead. |
gtk | Rust bindings and wrappers for GLib, GDK 3, GTK+ 3 and Cairo; the popular, platform independent GUI library. |
rust-qt | Do not use! In contrast to the gtk crate, this GUI library is incomplete and it seems it is no longer maintained. |
flutter-engine | Experimental! Flutter is Google’s portable UI toolkit for building beautiful, natively-compiled applications for mobile, web, and desktop from a single codebase. |
gfx | gfx is a high-performance, bindless graphics API for the Rust programming language. It aims to be the default API for Rust graphics: for one-off applications, or higher level libraries or engines. |
lazy_static | A macro for declaring lazily evaluated statics in Rust. Using this macro, it is possible to have statics that require code to be executed at runtime in order to be initialized. |
regex | A Rust library for parsing, compiling, and executing regular expressions. Its syntax is similar to Perl-style regular expressions, but lacks a few features like look around and backreferences. In exchange, all searches execute in linear time with respect to the size of the regular expression and search text. Much of the syntax and implementation is inspired by RE2. |
memmap | A cross-platform Rust API for memory mapped buffers. May be used to speed-up file-IO. |
rand | A Rust library for random number generation. Rand provides utilities to generate random numbers, to convert them to useful types and distributions, and some randomness-related algorithms. |
bastion | Bastion is a Fault-tolerant Runtime for Rust applications, a supervisor framework as known from Erlang. |
test-generator | Test-Generator provides the macros test_resources and bench_resources, executing a test for all items matching a specific glob-pattern, such as "res/tests/*.idl" |
test-generator-utest | Test-Generator-Utest providing 3-phase testing macro "utest!(setup, test, teardown)" |