From 72e4c1803f2275187ef65201d34c50bc1744db19 Mon Sep 17 00:00:00 2001 From: chrysn Date: Thu, 18 Nov 2021 11:51:57 +0100 Subject: [PATCH] rust: Add minimal test Unlike the hello-world example (that is largely identical), this gets run during CI. --- tests/rust_minimal/Cargo.lock | Bin 0 -> 19448 bytes tests/rust_minimal/Cargo.toml | 12 +++++ tests/rust_minimal/Makefile | 8 +++ tests/rust_minimal/README.md | 82 +++++++++++++++++++++++++++++ tests/rust_minimal/src/lib.rs | 15 ++++++ tests/rust_minimal/tests/01-run.py | 20 +++++++ 6 files changed, 137 insertions(+) create mode 100644 tests/rust_minimal/Cargo.lock create mode 100644 tests/rust_minimal/Cargo.toml create mode 100644 tests/rust_minimal/Makefile create mode 100644 tests/rust_minimal/README.md create mode 100644 tests/rust_minimal/src/lib.rs create mode 100755 tests/rust_minimal/tests/01-run.py diff --git a/tests/rust_minimal/Cargo.lock b/tests/rust_minimal/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..10e357c08665062571bc8569eafb75a0b11e551a GIT binary patch literal 19448 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 sZc}6I2Ia$FK"] +edition = "2018" +resolver = "2" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +riot-wrappers = "0.7" diff --git a/tests/rust_minimal/Makefile b/tests/rust_minimal/Makefile new file mode 100644 index 0000000000..37ef882eee --- /dev/null +++ b/tests/rust_minimal/Makefile @@ -0,0 +1,8 @@ +include ../Makefile.tests_common + +APPLICATION_RUST_MODULE = rust_minimal +BASELIBS += $(APPLICATION_RUST_MODULE).module + +FEATURES_REQUIRED += rust_target + +include $(RIOTBASE)/Makefile.include diff --git a/tests/rust_minimal/README.md b/tests/rust_minimal/README.md new file mode 100644 index 0000000000..f784f98e8c --- /dev/null +++ b/tests/rust_minimal/README.md @@ -0,0 +1,82 @@ +Test description +---------------- + +This test ensures that code produced through Rust can actually run; +it does that by simply printing "SUCCESS". + + +When things fail here +--------------------- + +This section is aimed at RIOT developers who are taken aback by this test failing +after they changed something completely unrelated. + +That can happen for two reasons: +For one, RIOT's API is not as strict as library APIs +(e.g. it is accepted that functions move between being `static inline` and not being), +and then, Rust is sometimes stricter than C when it comes to APIs +(e.g. no implicit numeric casting). + +The general strategy for addressing build failures resulting from this is: + +* Identify what breaks. + +* Update the `riot-sys` and `riot-wrappers` crates as necessary + to support both the old and the new version of the breaking piece. + + If actual workarounds (like an explicit cast) are needed to accommodate the old version, + a comment should indicate that this is for versions up to the current release, + to be eventually cleaned out when the crate bumps its minimum supported RIOT version. + +* Update the examples to use the new versions in a separate PR that just does + `cargo update` in the examples, and consequentally contains only Cargo.lock changes. + + Such a PR should be easy to get ACKed, as "CI says GO" is usually suffient for them. + +* Rebase the breaking PR on the one updating Cargo.lock. + +If old and new version can *not* be supported, +the affected crate should get a major release -- +but it's also grounds to revisit whether the change is actually as small as originally thought. +Then, the the Cargo.lock file can be updated in the very PR that introduces the breaking change. + +When, +for the above reasons or others, +a major release of creates is done, +their new versions should have a `.0-alpha.0` or similar release. +and a full release of the crate is done after the changing PR is merged. + +Common failure modes are: + +* Primitive types changed. + + This can trigger a change in Rust numeric internals, + which should then just take the larger of the different versions' types. + + If the type is publicly visible, it is usually already `usize` or a similar maximal type; + if not, and if using the new RIOT version means that the crate's API needs to change, + the crate needs to undergo a breaking release. + +* Functions are moved between static inline and linked. + + For the functions themselves, this is caught automatically because `riot-sys` + presents a unified view on symbols produced from linked and static functions. + If any such function takes a struct (even through a pointer), that struct's type changes. + The `inline_cast` function can be used to transmute the pointers with some safety checks. + +* Atomics are introduced. + + The C2Rust transpiler that allows using all the non-linked parts of the RIOT API + is incapable of handling atomics; + a workaround in `riot-sys`'s `riot-c2rust.h` file contains a list of headers + that do depend on `stdatomic.h` but don't really expose anything of that as their API; + they get included with a crude fake of atomics. + + If the addition of a board makes this test fail on that board only, + it is likely because that board's `board.h` pulls in stdatomic through one of the not yet cleared headers. + That file needs to be vetted for visible use of atomics, + and added to that list. + + diff --git a/tests/rust_minimal/src/lib.rs b/tests/rust_minimal/src/lib.rs new file mode 100644 index 0000000000..358a332ab2 --- /dev/null +++ b/tests/rust_minimal/src/lib.rs @@ -0,0 +1,15 @@ +// Copyright (C) 2020 Christian Amsüss +// +// This file is subject to the terms and conditions of the GNU Lesser +// General Public License v2.1. See the file LICENSE in the top level +// directory for more details. +#![no_std] + +use riot_wrappers::riot_main; +use riot_wrappers::println; + +riot_main!(main); + +fn main() { + println!("SUCCESS"); +} diff --git a/tests/rust_minimal/tests/01-run.py b/tests/rust_minimal/tests/01-run.py new file mode 100755 index 0000000000..026e7e6293 --- /dev/null +++ b/tests/rust_minimal/tests/01-run.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2021 Freie Universität Berlin +# 2021 Inria +# 2021 Kaspar Schleiser +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +import sys +from testrunner import run + + +def testfunc(child): + child.expect_exact('SUCCESS') + + +if __name__ == "__main__": + sys.exit(run(testfunc))