Выбрать главу

match_args {increase|decrease} <integer>

Увеличивает или уменьшает число на 1.

$ ./match_args increase 42

43

Rust предоставляет интерфейс внешних функций (Foreign Function Interface, FFI) к библиотекам, написанным на языке С. Внешние функции должны быть объявлены внутри блока extern и аннотированы при помощи атрибута #[link], который содержит имя внешней библиотеки.

use std::fmt;

// Этот extern-блок подключает библиотеку libm

#[link(name = "m")]

extern {

// Это внешняя функция, которая считает квадратный корень

// комплексного числа одинарной точности

fn csqrtf(z: Complex) -> Complex;

fn ccosf(z: Complex) -> Complex;

}

// Так как вызовы внешних функций считаются unsafe,

// принято писать над ними обёртки.

fn cos(z: Complex) -> Complex {

unsafe { ccosf(z) }

}

fn main() {

// z = -1 + 0i

let z = Complex { re: -1., im: 0. };

// вызов внешней функции - unsafe операция

let z_sqrt = unsafe { csqrtf(z) };

println!("квадратный корень от {:?} равен {:?}", z, z_sqrt);

// вызов безопасного API в котором находится unsafe операция

println!("cos({:?}) = {:?}", z, cos(z));

}

// Минимальная реализация комплексного числа одинарной точности

#[repr(C)]

#[derive(Clone, Copy)]

struct Complex {

re: f32,

im: f32,

}

impl fmt::Debug for Complex {

fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

if self.im < 0. {

write!(f, "{}-{}i", self.re, -self.im)

} else {

write!(f, "{}+{}i", self.re, self.im)

}

}

}

Rust - это язык программирования, который очень заботится о корректности и включает в себя поддержку написания тестов программного обеспечения в самом языке.

Тестирование поставляется в трёх стилях:

   • Модульное тестирование.

   • Тестирование кода из примеров документации.

   • Интеграционное тестирование.

Также Rust поддерживает указание дополнительных зависимостей для тестов:

   • Dev-dependencies

   • Глава о тестировании в "The Rust Programming Language"

   • Описание API для тестирования примеров из документации.

Тесты - это функции на Rust, которые проверяют, что тестируемый код работает ожидаемым образом. Тело тестовых функций обычно выполняет некоторую настройку, запускает код, который мы тестируем, и затем сравнивает полученный результат с тем, что мы ожидаем.

Большинство модульных тестов располагается в модуле tests, помеченном атрибутом #[cfg(test)]. Тестовые функции помечаются атрибутом #[test].

Тесты заканчиваются неудачей, когда что-либо в тестовой функции вызывает панику. Есть несколько вспомогательных макросов:

   • assert!(expression) - паникует, если результат выражения равен false.

   • assert_eq!(left, right) и assert_ne!(left, right) - сравнивает левое и правое выражения на равенство и неравенство соответственно.

pub fn add(a: i32, b: i32) -> i32 {

a + b

}

// Это действительно плохая функция сложения, её назначение в данном // примере - потерпеть неудачу.

#[allow(dead_code)]

fn bad_add(a: i32, b: i32) -> i32 {

a - b

}

#[cfg(test)]

mod tests {

// Обратите внимание на эту полезную идиому: импортирование имён из внешней (для mod - тестов) области видимости.

use super::*;

#[test]

fn test_add() {

assert_eq!(add(1, 2), 3);

}

#[test]

fn test_bad_add() {

// Это утверждение запустится и проверка не сработает.

// Заметьте, что приватные функции также могут быть протестированы!

assert_eq!(bad_add(1, 2), 3);

}

}

Тесты могут быть запущены при помощи команды cargo test.

$ cargo test

running 2 tests

test tests::test_bad_add ... FAILED

test tests::test_add ... ok

failures:

---- tests::test_bad_add stdout ----

thread 'tests::test_bad_add' panicked at 'assertion failed: `(left == right)`