Продолжаю изучать раст.
В настоящее время у меня код такой:
src/lib.rs:
#![allow(stable_features)]
#![allow(dead_code)]
#![feature(static_recursion)]
#![allow(non_upper_case_globals)]
use std::ffi::CStr;
use std::os::raw::c_char;
mod t;
struct Man {
name: &'static str,
car: &'static Car,
}
struct Car {
owner: &'static Man,
id: i32,
}
static vasya:Man = Man{car: &vaz, name: "Vasya"};
static vaz:Car = Car{owner: &vasya, id:30};
static vova:Man = Man{car: &mers, name: "Vova"};
static mers:Car = Car{owner: &vova, id:31};
static all:[&Man; 2] = [&vasya, &vova];
#[no_mangle]
pub extern fn get_id_by_name( name: *const c_char) -> i32{
let need_name = unsafe{ CStr::from_ptr(name) }.to_str();
match need_name {
Ok(n) => {
println!("query name = {}", n);
for x in all.iter() {
if n == x.name {
return x.car.id;
}
}
0
}
,
Err(e) => {
println!("error {}", e);
-1
},
}
}
src/t.rs:
#[cfg(test)]
mod tests {
use get_id_by_name;
use std::ffi::CString;
#[test]
fn test_get_id_by_name(){
println!("тест начался!");
let s = CString::new("Vova").unwrap();
let id1 = get_id_by_name(s.as_ptr());
println!("id={}", id1);
assert_eq!(id1, 32);
println!("тест завершен!")
}
#[test]
fn test_get_id_by_name2(){
}
}
Cargo.toml:
[package]
name = "name2id"
version = "0.1.0"
[lib]
name = "name2id"
path = "src/lib.rs"
test = true
crate-type = ["cdylib"]
main.c:
#include <stdio.h>
extern int get_id_by_name(const char * name);
int main(){
int id1 = get_id_by_name("Vasya");
int id2 = get_id_by_name("Vova");
int id3 = get_id_by_name("zzz");
printf("id1=%d id2=%d id3=%d\n", id1, id2, id3);
}
Сишник собираю командой: gcc main.c -L . -lname2id (предварительно руками подложив к сишнику собранный so-шник)
Значит, что мне тут не нравится.
-
Строчка mod t в фале lib.rs, которой я загружаю модуль юнит тестов. Получается, что как бы либа должна знать о своих тестах. Но ведь должно быть наоборот: это надо в тесте ссылаться на либу. А либа о тестах, которыми ее тестируют, не должна знать ничего! Как такое сделать? В идеале хотелось бы как-то сказать об этом в Cargo.toml, что мол вот у тебя тесты, а вот тут - либа. Но сколько я ни читал документации, не нашел такого.
-
Есть подозрение насчет строчки:
let need_name = unsafe{ CStr::from_ptr(name) }.to_str();
Собственно подозрение - а правильно ли я делаю? У меня такое подозрение, что компилятор не ругается потому, что стоит unsafe, но вообще так делать нельзя, т.к. все уничтожается при выходе из { }, а потом я беру to_str() от уже уничтоженного объекта. -
Чем в понимании руста отличаются юнит-тесты от интеграционных тестов? Для интеграицонных руст выполняет какие-то предварительные действия? Или с этой точки зрения они вообще ничем не отличаются?
-
На самом деле, данный вопрос идет уже не конктексте сравнения rust и си, а в контексте сравнения с java, но тем не менее. Есть ли возможность подложить на время теста mock-обьект? Впринципе, я понимаю, что раз я могу либу утянуть и использовать вне растового окружения, то такая возможность, очевидно, есть. Для этого функции, которые нужно при тестах подменять, надо будет обьявить как extern и их можно линковать с разными либами при тестах и для релиза. Это понятно. Вопрос в том, а можно ли такое делать средствами rust?