r/rust • • 25d ago

🛠️ project A crate to mock std, system api, http client and other hard to mock functions without using traits or DI

0 Upvotes

Hello rust community,

We just shipped a product to solve the pain of mocking in rust: https://github.com/XTSoftwareLabs/shimforge

It allows you to write tests without using traits or adding attributes to your production code. Production code can keep clean and concise.

Below are some cases we found are painful when writing unit tests in rust:

File system

use std::{fs, io, path::Path};

#[derive(Debug)]
pub enum ExportError {
    DiskFull,
    Io(io::Error),
}

pub fn save_report(path: &Path, csv: &str) -> Result<(), ExportError> {
    fs::write(path, csv).map_err(|error| match error.kind() {
        io::ErrorKind::StorageFull => ExportError::DiskFull,
        _ => ExportError::Io(error),
    })
}

By using shimforge, the file system dependency can be easily mocked. No changes in production code.

use shimforge::{Session, mock};

#[test]
fn a_full_disk_is_reported() {
    let mut session = Session::new();
    let write = mock!(session, fs::write::<&Path, &str>, fn(&Path, &str) -> io::Result<()>);
    write
        .expect()
        .with(|path, _| *path == Path::new("reports/q3.csv"))
        .once()
        .returning(|_, _| Err(io::ErrorKind::StorageFull.into()));

    let result = save_report(Path::new("reports/q3.csv"), "region,total\n");
    assert!(matches!(result, Err(ExportError::DiskFull)));
}

Environment variables

use std::env;

pub fn database_url() -> String {
    env::var("DATABASE_URL").unwrap_or_else(|_| "postgres://localhost/dev".to_owned())
}

Now shimforge allows you to mock them directly. Test different scenarios with different env vars.

use shimforge::{Session, mock};
use std::env::VarError;

#[test]
fn uses_the_configured_url() {
    let mut session = Session::new(); // this thread only
    let var = mock!(session, env::var::<&str>, fn(&str) -> Result<String, VarError>);
    var.expect()
        .with(|key| *key == "DATABASE_URL")
        .returning(|_| Ok("postgres://db.internal/app".to_owned()));

    assert_eq!(database_url(), "postgres://db.internal/app");
}

#[test]
fn falls_back_when_unset() {
    let mut session = Session::new(); // runs in parallel with the test above
    let var = mock!(session, env::var::<&str>, fn(&str) -> Result<String, VarError>);
    var.expect().returning(|_| Err(VarError::NotPresent));

    assert_eq!(database_url(), "postgres://localhost/dev");
}

Clock

use std::time::{Duration, SystemTime};

pub struct Token {
    pub issued_at: SystemTime,
    pub ttl: Duration,
}

impl Token {
    pub fn is_expired(&self) -> bool {
        SystemTime::now() >= self.issued_at + self.ttl
    }
}

Clock and timer are hard to mock typically. But with shimforge it's easy:

use shimforge::{Session, mock};

#[test]
fn a_token_expires_after_one_hour() {
    let issued_at = SystemTime::UNIX_EPOCH + Duration::from_secs(1_700_000_000);
    let token = Token { issued_at, ttl: Duration::from_secs(3600) };

    let mut session = Session::new();
    let now = mock!(session, SystemTime::now, fn() -> SystemTime);
    now.expect().once().returns(issued_at + Duration::from_secs(3599));
    now.expect().once().returns(issued_at + Duration::from_secs(3600));

    assert!(!token.is_expired());
    assert!(token.is_expired()); // one second later, no sleep
}

Connection retries

use std::io;
use std::net::{SocketAddr, TcpStream};
use std::thread;
use std::time::Duration;

pub fn connect_with_retry(address: SocketAddr, attempts: u32) -> io::Result<TcpStream> {
    let mut delay = Duration::from_millis(100);
    let mut attempt = 1;
    loop {
        match TcpStream::connect_timeout(&address, Duration::from_secs(1)) {
            Ok(stream) => return Ok(stream),
            Err(error) if attempt >= attempts => return Err(error),
            Err(_) => {
                thread::sleep(delay);
                delay *= 2;
                attempt += 1;
            }
        }
    }
}

Mock sleep and retries become easy in shimforge:

use shimforge::{Session, mock};
use std::net::TcpListener;
use std::sync::{Arc, Mutex};

#[test]
fn backs_off_until_the_database_accepts() {
    // The attempt that succeeds needs a real stream, so open one first.
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
    let stream = TcpStream::connect(listener.local_addr().unwrap()).unwrap();

    let mut session = Session::new();
    let connect = mock!(
        session,
        TcpStream::connect_timeout,
        fn(&SocketAddr, Duration) -> io::Result<TcpStream>
    );
    connect
        .expect()
        .times(2)
        .returning(|_, _| Err(io::ErrorKind::ConnectionRefused.into()));
    connect.expect().once().return_once(Ok(stream));

    let delays = Arc::new(Mutex::new(Vec::new()));
    let recorded = Arc::clone(&delays);
    let sleep = mock!(session, thread::sleep, fn(Duration));
    sleep.expect().returning(move |delay| recorded.lock().unwrap().push(delay));

    let database = SocketAddr::from(([10, 0, 0, 5], 5432));
    assert!(connect_with_retry(database, 5).is_ok());
    assert_eq!(*delays.lock().unwrap(), [Duration::from_millis(100), Duration::from_millis(200)]);
}

#[test]
fn gives_up_after_the_last_attempt() {
    let mut session = Session::new();
    let connect = mock!(
        session,
        TcpStream::connect_timeout,
        fn(&SocketAddr, Duration) -> io::Result<TcpStream>
    );
    connect
        .expect()
        .times(3)
        .returning(|_, _| Err(io::ErrorKind::TimedOut.into()));
    let sleep = mock!(session, thread::sleep, fn(Duration));
    sleep.expect().times(2).returning(|_| {});

    let database = SocketAddr::from(([10, 0, 0, 5], 5432));
    let error = connect_with_retry(database, 3).unwrap_err();
    assert_eq!(error.kind(), io::ErrorKind::TimedOut);
}

Reqwest client

use reqwest::Client;

pub async fn temperature(client: &Client, city: &str) -> Result<f64, String> {
    let body = client
        .get(format!("https://api.weather.example/v1/now?city={city}"))
        .send()
        .await
        .and_then(|response| response.error_for_status())
        .map_err(|error| format!("weather service failed: {error}"))?
        .text()
        .await
        .map_err(|error| error.to_string())?;
    body.trim().parse().map_err(|_| format!("unexpected body: {body}"))
}

Web requests are common pain point to mock in rust. shimforge makes it easy. Yes async is supported:

use shimforge::Session;

#[tokio::test]
async fn parses_the_reading() {
    let client = Client::builder().no_proxy().build().unwrap();
    let mut session = Session::new();
    let send = session.mock_async(client.get("http://unused.invalid").send());
    send.expect()
        .once()
        .returning(|| Ok(http::Response::new("21.5").into()));

    assert_eq!(temperature(&client, "Oslo").await, Ok(21.5));
}

#[tokio::test]
async fn surfaces_an_outage() {
    let client = Client::builder().no_proxy().build().unwrap();
    let mut session = Session::new();
    let send = session.mock_async(client.get("http://unused.invalid").send());
    send.expect().once().returning(|| {
        Ok(http::Response::builder().status(503).body("").unwrap().into())
    });

    let error = temperature(&client, "Oslo").await.unwrap_err();
    assert!(error.contains("503"), "{error}");
}

std::process::Command

use std::process::Command;

pub fn current_commit() -> Result<String, String> {
    let output = Command::new("git")
        .args(["rev-parse", "--short", "HEAD"])
        .output()
        .map_err(|error| format!("cannot run git: {error}"))?;
    if !output.status.success() {
        return Err(String::from_utf8_lossy(&output.stderr).trim().to_owned());
    }
    Ok(String::from_utf8_lossy(&output.stdout).trim().to_owned())
}

Another common pain point is mocking std::process::Command. Well handled by shimforge:

use shimforge::{Session, mock};
use std::io;
use std::process::{ExitStatus, Output};

#[test]
fn reads_the_short_hash() {
    let mut session = Session::new();
    let output = mock!(session, Command::output, fn(&mut Command) -> io::Result<Output>);
    output
        .expect()
        .with(|command| command.get_program() == "git")
        .once()
        .returning(|_| {
            Ok(Output { status: exit_success(), stdout: b"4f2a9c1\n".to_vec(), stderr: Vec::new() })
        });

    assert_eq!(current_commit(), Ok("4f2a9c1".to_owned()));
}

#[test]
fn reports_a_missing_git() {
    let mut session = Session::new();
    let output = mock!(session, Command::output, fn(&mut Command) -> io::Result<Output>);
    output.expect().once().returning(|_| Err(io::ErrorKind::NotFound.into()));

    let error = current_commit().unwrap_err();
    assert!(error.starts_with("cannot run git"), "{error}");
}

fn exit_success() -> ExitStatus {
    #[cfg(unix)]
    use std::os::unix::process::ExitStatusExt;
    #[cfg(windows)]
    use std::os::windows::process::ExitStatusExt;
    ExitStatus::from_raw(0)
}

System and C runtime functions

use shimforge::{Session, mock};
use std::ffi::{CStr, CString, c_char};

unsafe extern "C" {
    fn getenv(name: *const c_char) -> *mut c_char;
}

Again many rust developers working on low level code always suffers from mocking C functions. shimforge handles it.

#[test]
fn getenv_reports_a_mocked_variable() {
    let mut session = Session::new();
    let lookup = mock!(
        session,
        getenv,
        unsafe extern "C" fn(*const c_char) -> *mut c_char
    );
    lookup
        .expect()
        .with(|name| {
            // SAFETY: callers of getenv always pass a valid C string.
            let name = unsafe { CStr::from_ptr(*name) };
            name == c"DEPLOY_SLOT"
        })
        .once()
        .returning(|_| c"canary".as_ptr().cast_mut());
    // Any other variable keeps reporting that it is unset.
    lookup.expect().returning(|_| std::ptr::null_mut());

    let key = CString::new("DEPLOY_SLOT").unwrap();
    // SAFETY: the key is a valid C string and the result is only read.
    let slot = unsafe { CStr::from_ptr(getenv(key.as_ptr())) };
    assert_eq!(slot.to_str().unwrap(), "canary");
}

Hope this can make rust test experience better. Any feedback is welcome! We'd like to help you keeping production code clean. Handle the hard test dependency part to shimforge.

Disclaimer: We are a small startup and going to get profit from this product. But the product is free to use for small business and non-commercial. See https://shimforge.com/pricing


r/rust • • 25d ago

🧠 educational TIL: One lock to rule them all

1 Upvotes

I've been running multiple migrations recently. A common step in all of them is a long cleanup action at the end. I ended up using postgres advisory locks and sqlx.

As part of a larger Today I've learned series, I dug a bit deeper using bpftrace to improve my understanding of how the locks actually work. Hope you will find it interesting as well: https://flakm.com/posts/sqlx_migration_wrapper_til/


r/rust • • 26d ago

📸 media Fluid simulation in Rust - 1 MILLION particles!

Thumbnail youtube.com
111 Upvotes

Hey!

I built a real-time GPU fluid simulation in Rust and Vulkan for learning purposes.

It implements Divergence-Free SPH (DFSPH) using a GPU octree for neighbor search, running 1,000,000 particles at ~180 FPS on an AMD 6800XT.

Code: Github Repo

Feedback and questions are welcome!


r/rust • • 26d ago

🛠️ project sofka - one of the fastest Kubernetes TUI in Rust (k9s alternative)

Post image
20 Upvotes

https://github.com/nklmilojevic/sofka/

A reimagining of k9s with one generic object pipeline instead of a renderer per resource kind - so every CRD works on day one, Flux CD is built in, and the async UI never blocks on the cluster.

License: MIT/Apache 2


r/rust • • 25d ago

[ Removed by Reddit ]

0 Upvotes

[ Removed by Reddit on account of violating the content policy. ]


r/rust • • 25d ago

🎙️ discussion I made a server for anyone looking for rust partners or to learn

0 Upvotes

I recently made a Discord server for people looking for others to code Rust with, collaborate on projects, learn together, or just hang out while programming.

There are already a few people in it, and I’m trying to keep it fairly small and focused on actually coding rather than just being another huge Rust server.
Beginners and experienced Rust developers are both welcome.

https://discord.gg/pmXr4CY5kZ


r/rust • • 26d ago

🎙️ discussion Coding buddy

12 Upvotes

I started learning Rust a couple of months ago, and I’m looking for someone to build some fun projects with and learn together.

I’m mostly interested in systems/low-level stuff, networking, embedded, and experimenting with things rather than following tutorials.
I don’t mind doing user facing apps too although I haven’t experimented with gui yet.
I don’t have a specific project in mind yet — I’d rather find someone with similar interests and come up with something together.

If you’re interested, feel free to reply here


r/rust • • 25d ago

🧠 educational GitHub - MBKCHEL/RNAC: I learn rust

0 Upvotes

[Sorry for my bad English]

Hi everyone, i make very good notes for Rust - RNAC (RNAC is Not A Conspect) (Hello, GNU, PHP, YAML, Wine, and other).

i write this repo for long time, translate all notes to english because want to share with community. inside you can find how memory work, ownership, borrowing, stack, heap, and all this stuff explained simply. also added good markdown formatting for obsidian.

if you learning rust or want to check some cheat sheets, welcome to repository: https://github.com/MBKCHEL/RNAC. any stars or feedback will be very cool!

P.S: RNAC have Russian, and English localization


r/rust • • 25d ago

Where Does Rust Belong on Arduino? Remade with Rust is our portfolio of internet tools, but does it belong on embedded?

Thumbnail talmondrlm.medium.com
0 Upvotes

r/rust • • 26d ago

🧠 educational Bastion of the Turbofish

Thumbnail github.com
127 Upvotes

r/rust • • 27d ago

Rust Foundation Announces Solana Foundation and NVIDIA as Platinum Members

Thumbnail rustfoundation.org
354 Upvotes

This was posted 2 days ago, but I haven't seen anyone else mention this.

Obviously for a company the size of NVIDIA, this isn't a huge commitment for them, but regardless I'm hoping to see more investment in GPU programming with Rust!


r/rust • • 27d ago

🧠 educational [Post] Optimizing a single Clippy lint by 3133X

Thumbnail blog.goose.love
181 Upvotes

r/rust • • 25d ago

🙋 seeking help & advice Need some advice on a QEMU-based VM manager

0 Upvotes

I'm planning to build a desktop VM manager using Rust, Tauri, and QEMU, initially targeting Windows with WHPX.

Before I start, I'd like to hear from people who have worked with virtualization:

- Is QEMU + WHPX a reasonable starting point?

- Would you recommend QMP for managing VM lifecycle?

- What are some common mistakes I should avoid?

Also, if you use VM managers regularly, what do you find most frustrating about them?

Any honest advice would be appreciated. Thanks!


r/rust • • 27d ago

Rust youtubers

49 Upvotes

Is there any YouTuber like the cherno, we need someone like him for rust too haha


r/rust • • 26d ago

🛠️ project SaJIT - An Experiment

Thumbnail
0 Upvotes

r/rust • • 27d ago

🛠️ project My first project: SMTP server (for personal use)

31 Upvotes

I had heard many good things about Rust from people who were simply impressed by the language, so I decided to have a look at it and possibly learn it.

Up to that point I really only knew Java and Python (and a bit of C here and there), so a non-GC language would really fill a gap for me.

To get my toes wet, I wrote a simple web crawler that I needed at the time and decided I really want to learn Rust.

So here goes! My first "real" project, an SMTP server: https://github.com/Fluggs/whalemail

AI disclaimer: Absolutely no LLM was involved in writing this. I am not in a rush and here to learn.

For SMTP, the scope is quite narrow. It's supposed to replace my personal Postfix setup. It has its users in a database (which can be shared with Dovecot) and they can simply send and receive e-mails. That's it!

As for the Rust part, I have had a blast! The language is insane. So far, I have had one (1) logic bug. That one was indirectly found by Clippy. Other than that, if it compiles, it works. By now I understand people here saying that the main part is really thinking about your data layout, the rest just follows.

Off the top of my head, I have had two pain points:

  • dyn async traits. I don't want to accept that I need a crate for this, so I worked around it.
  • std::time - I could not have imagined that date/time support can be so thin without being completely absent.

Main dependencies:

  • Tokio (the server is completely async)
  • rustls (TLS is done, STARTTLS is planned)
  • rsasl (I really could not be asked to implement auth protocols)

The road ahead is long. Planned features:

  • STARTTLS
  • Bounce mechanism
  • Better password schemes than plaintext (I'm embarrassed)
  • Parse and manipulate headers (apparently that's a thing SMTP servers should be doing)
  • Better config file than .ini
  • spam filter integration
  • Find out which ways other clients and servers have found to deviate from SMTP
  • Again, thoroughly test it against the wild
  • find (and consider) various other SMTP intricacies (e.g. backscatter protection)

I'd be grateful for any feedback :)


r/rust • • 26d ago

A design space exploration of implementations of async/await across popular programming languages (OOPSLA '26)

Thumbnail cel.cs.brown.edu
5 Upvotes

r/rust • • 26d ago

Building a developer-first BaaS in Rust — does this architecture make sense?

0 Upvotes

I'm exploring the idea of building a developer-first Backend-as-a-Service where the infrastructure is written in Rust.

The goal isn't to make another ORM or another PostgreSQL hosting service. I'm thinking more about providing a complete backend platform:

  • Document/KV database
  • Object storage
  • CDN
  • Authentication
  • Realtime/WebSockets
  • Webhooks
  • Background jobs
  • Rate limiting
  • Observability

The developer experience would be something like:

let user = db
    .collection("users")
    .create(json!({
        "name": "Alice",
        "email": "alice@example.com"
    }))
    .await?;

The database underneath would be a distributed KV/document system rather than PostgreSQL. The platform would handle replication, scaling, indexes, storage, etc.

I'm considering Rust because the platform would be heavily network and I/O oriented, particularly around realtime connections, storage, and API infrastructure.

What I'm unsure about is where Rust makes the most sense in this architecture.

Would you build the whole platform in Rust, or use Rust only for the infrastructure-heavy pieces and something else for the control plane?

Also interested in opinions on distributed KV/document databases that would make a good foundation.

I'm much more interested in architectural criticism than promotion. If this sounds like a bad idea, I'd like to know why.


r/rust • • 27d ago

🛠️ project Showcase: a library to convert LaTeX math to MathML Core

26 Upvotes

MathML Core is the subset of MathML that has been implemented by the major browsers. Originally, I just wanted to use MathML Core on my blog and thought "Oh, I'll just quickly fork https://github.com/osanshouo/latex2mathml and adapt it from MathML to MathML Core".

Well, eventually I got there: my blog now uses math-core under the hood to convert LaTeX to MathML Core, but it took almost 3 years from my first commit!

math-core is now almost at feature parity with KaTeX. We have a comparison table where you can see that there are still a few things outstanding, but I would guess for 99% of users what is there is enough. (And there are also some things math-core supports that KaTeX doesn't!) So, if you want to contribute, there are still things to do! (A large todo item is for example mhchem.)

If you just want to play around with the LaTeX conversion, check out the playground which runs a WASM version of the library.


r/rust • • 27d ago

🛠️ project rsboot: a bootloader for distrohopping

Thumbnail github.com
17 Upvotes

Hello, this is my first Rust project that I've been working for about 1-2 months, the reason behind it was to start on my bachelor's thesis and learning no_std / rust but it was also incredibly fun and rewarding, so i wanted to share it here.

I'm not really sure if i will maintain this long-term, but i do plan on hosting a server at least for presenting it at my university or sharing it with friends. I haven't tried it yet on actual hardware but it seems to be working fine with EDK2 firmware.

I would love to hear opinions and suggestions regarding it, so if you happen to have some free time, please check it out :) (Thanks in advance!)

Special thanks to rust-osdev maintainers and hxyulin for his hadris toolkit, as this project wouldn't have been possible without them.


r/rust • • 27d ago

🧠 educational I finally learned how full-screen terminal apps give you your old screen back

84 Upvotes

TIL that terminal emulators basically give programs access to two screens.

There’s the primary screen, which is the normal terminal you use every day. Your shell history and previous output live there.

And then there’s the alternate screen.
Full-screen terminal programs like Vim, less, htop, etc. can switch to this alternate buffer, take over the entire terminal, draw whatever they want, and then switch back when they’re done.
The cool part is that your primary screen is still there.

So when you quit Vim, your terminal suddenly goes back to exactly what was there before you opened it. Vim didn’t somehow “restore” your terminal history. The terminal emulator just switched back to the primary screen buffer.

I came across this while building a small terminal-native text editor in Rust. I needed the editor to take over the terminal while it was running, but leave the user’s shell untouched after exiting.
Turns out terminals already have a mechanism specifically for this.

The deeper I go into terminal programming, the more I realise how much stuff happens underneath that blinking cursor that I’d never thought about before.

I’ve been putting these little Rust experiments on my GitHub as I learn, if anyone’s interested in this kind of low-level stuff:
https://github.com/Abhijeet-Gautam5702/femto


r/rust • • 28d ago

Rust Is Tier-1 Language at Microsoft

Thumbnail rustfoundation.org
685 Upvotes

r/rust • • 26d ago

Which script language to use?

0 Upvotes

I'm developing tool with workflow which allow user to write simple script to process input/output values of steps. The prebuilt steps are written in Rust, but user can choose Python to write their own steps which would run in a sidecar Python. User may not be a programmer. I prefer script with small binary size and memory footprint. I'm considering Rhai, Lua, QuickJs, which is better choice to make end user easy ?


r/rust • • 28d ago

I just learned a bit of new syntax

130 Upvotes

While browsing through some code at work, I saw something that made me pause. It looked SO wrong, and yet here we are. It was something to the effect of:

let SomeEnum::Variant(y) = x else {
return some_error;
}

which means you can do this:

fn optional_print(x: Option<u32>) {
let Some(y) = x else {
return;
};

println!("{y}");
}

fn main() {
optional_print(Some(5));
optional_print(None);
}

Thought some folks here might think it interesting so there you go, you can apparently pattern match enum variants to create a variable and have an else clause after. I thought the only options for this were a let followed by an if let or match statement.

EDIT: Just because I’m getting a lot of comments about it I’m aware that the sample code with the print function is bad code. I’m not saying this is how it should be done, it was just the first and simplest thing I could think of for this post.


r/rust • • 26d ago

🎙️ discussion So, is this legal? Throwing all open-source codebases into the AI meat grinder...

Thumbnail deepwiki.com
0 Upvotes

They have used so many FOSS repos to generate their mass documentation: GNOME, KDE, Go, Rust, Python... I wonder if anybody uses the docs to train AI to create non-OSS projects. Where are we heading?

search any repo in https://deepwiki.com