use native_neural_network_std::std::activations_std::ActivationKind;
use native_neural_network_std::std::layers_std::{DenseLayerDesc, LayerSpec};
fn make_valid_blob() -> Vec<u8> {
use native_neural_network_std::std::model_format_std::{encode_model_v1, encoded_size_v1};
let layers = vec![LayerSpec::Dense(DenseLayerDesc {
input_size: 2,
output_size: 1,
weight_offset: 0,
bias_offset: 0,
activation: ActivationKind::Identity,
})];
let weights = vec![1.0f32, 1.0f32];
let biases = vec![0.5f32];
let size = encoded_size_v1(layers.len(), weights.len(), biases.len()).expect("encoded size");
let mut out_bytes = vec![0u8; size];
let written =
encode_model_v1(&layers, &weights, &biases, &mut out_bytes).expect("encode valid ffi blob");
out_bytes.truncate(written);
out_bytes
}
#[test]
fn cpu_backend_abstraction_real() {
let previous = native_neural_network_std::std::engine_std::get_compute_backend();
native_neural_network_std::std::engine_std::set_compute_backend(
native_neural_network_std::std::engine_std::ComputeBackend::Cpu,
);
assert_eq!(
native_neural_network_std::std::engine_std::get_compute_backend(),
native_neural_network_std::std::engine_std::ComputeBackend::Cpu
);
native_neural_network_std::std::engine_std::set_compute_backend(previous);
}
#[test]
fn ffi_api_version_real() {
let v = native_neural_network_std::std::ffi::rnn_ffi_api_version();
assert_eq!(v, 1, "mocked FFI should return version 1");
}
#[test]
fn ffi_api_version_threadsafe() {
use std::thread;
let mut handles = Vec::new();
for _ in 0..8 {
handles.push(thread::spawn(|| {
native_neural_network_std::std::ffi::rnn_ffi_api_version()
}));
}
for h in handles {
let v = h.join().unwrap();
assert_eq!(v, 1);
}
}
#[test]
fn ffi_model_lifecycle_and_run() {
let blob = make_valid_blob();
let h = native_neural_network_std::std::ffi::rnn_ffi_model_create_from_bytes_v1(&blob);
assert!(h != 0);
let info = native_neural_network_std::std::ffi::rnn_ffi_model_get_info(h).expect("get_info");
assert_eq!(
info.len(),
core::mem::size_of::<native_neural_network_std::std::ffi::RnnFfiModelInfo>()
);
let input = [2.0f32, 3.0f32];
let mut out = [0f32; 1];
let rc2 = native_neural_network_std::std::ffi::rnn_ffi_model_run(h, &input, &mut out);
assert_eq!(rc2, 0);
assert!((out[0] - (2.0 + 3.0 + 0.5)).abs() < 1e-6);
native_neural_network_std::std::ffi::rnn_ffi_model_destroy(h);
}
#[test]
fn ffi_run_with_bad_buffers_errors() {
let blob = make_valid_blob();
let h = native_neural_network_std::std::ffi::rnn_ffi_model_create_from_bytes_v1(&blob);
assert!(h != 0);
let input = [0f32; 2];
let mut out = [0f32; 0];
let rc = native_neural_network_std::std::ffi::rnn_ffi_model_run(h, &input, &mut out);
assert!(rc < 0);
native_neural_network_std::std::ffi::rnn_ffi_model_destroy(h);
}
#[test]
fn ffi_concurrent_create_run_destroy() {
use std::thread;
let mut handles = Vec::new();
for _ in 0..8 {
handles.push(thread::spawn(|| {
let blob = make_valid_blob();
let h = native_neural_network_std::std::ffi::rnn_ffi_model_create_from_bytes_v1(&blob);
if h == 0 {
panic!("create failed");
}
let input = [1.0f32, 1.0f32];
let mut out = [0f32; 1];
let rc = native_neural_network_std::std::ffi::rnn_ffi_model_run(h, &input, &mut out);
assert_eq!(rc, 0);
native_neural_network_std::std::ffi::rnn_ffi_model_destroy(h);
}));
}
for h in handles {
h.join().unwrap();
}
}