From 750f1df1367982015fd3d57cfecd5544b03d3a4a Mon Sep 17 00:00:00 2001 From: "Carson M." Date: Sat, 22 Mar 2025 23:44:02 -0500 Subject: [PATCH] tests: add valgrind sample program --- .cargo/config.toml | 1 + Cargo.toml | 3 +- tests/leak-check/Cargo.toml | 12 +++ tests/leak-check/main.rs | 162 ++++++++++++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 tests/leak-check/Cargo.toml create mode 100644 tests/leak-check/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 2854782..3ec0bf6 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -11,3 +11,4 @@ example-train-pretokenize = ["run", "--manifest-path", "examples/training/Cargo. example-train-clm = ["run", "--manifest-path", "examples/training/Cargo.toml", "--example", "train-clm", "--target-dir", "target"] example-train-clm-simple = ["run", "--manifest-path", "examples/training/Cargo.toml", "--example", "train-clm-simple", "--target-dir", "target"] example-yolov8 = ["run", "--manifest-path", "examples/yolov8/Cargo.toml", "--example", "yolov8", "--target-dir", "target"] +leak-check = ["valgrind", "run", "--manifest-path", "tests/leak-check/Cargo.toml", "--target-dir", "target"] diff --git a/Cargo.toml b/Cargo.toml index 2f634dc..b6629f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,8 @@ exclude = [ 'examples/sentence-transformers', 'examples/training', 'examples/wasm-emscripten', - 'examples/yolov8' + 'examples/yolov8', + 'tests/leak-check' ] [package] diff --git a/tests/leak-check/Cargo.toml b/tests/leak-check/Cargo.toml new file mode 100644 index 0000000..38868f0 --- /dev/null +++ b/tests/leak-check/Cargo.toml @@ -0,0 +1,12 @@ +[package] +publish = false +name = "leak-check" +version = "0.0.0" +edition = "2021" + +[[bin]] +name = "leak-check" +path = "main.rs" + +[dependencies] +ort = { path = "../../", features = [] } diff --git a/tests/leak-check/main.rs b/tests/leak-check/main.rs new file mode 100644 index 0000000..df058a1 --- /dev/null +++ b/tests/leak-check/main.rs @@ -0,0 +1,162 @@ +use ort::{ + adapter::Adapter, + execution_providers::CPUExecutionProvider, + memory::{AllocationDevice, Allocator, AllocatorType, MemoryInfo, MemoryType}, + operator::{ + Operator, OperatorDomain, + io::{OperatorInput, OperatorOutput}, + kernel::{Kernel, KernelAttributes, KernelContext} + }, + session::{RunOptions, Session}, + tensor::TensorElementType, + value::Tensor +}; + +struct CustomOpOne; + +impl Operator for CustomOpOne { + fn name(&self) -> &str { + "CustomOpOne" + } + + fn inputs(&self) -> Vec { + vec![OperatorInput::required(TensorElementType::Float32), OperatorInput::required(TensorElementType::Float32)] + } + + fn outputs(&self) -> Vec { + vec![OperatorOutput::required(TensorElementType::Float32)] + } + + fn create_kernel(&self, _: &KernelAttributes) -> ort::Result> { + Ok(Box::new(|ctx: &KernelContext| { + let x = ctx.input(0)?.unwrap(); + let y = ctx.input(1)?.unwrap(); + let (x_shape, x) = x.try_extract_tensor::()?; + let (y_shape, y) = y.try_extract_tensor::()?; + + let mut z = ctx.output(0, x_shape.to_vec())?.unwrap(); + let (_, z_ref) = z.try_extract_tensor_mut::()?; + for i in 0..y_shape.iter().copied().reduce(|acc, e| acc * e).unwrap() as usize { + if i % 2 == 0 { + z_ref[i] = x[i]; + } else { + z_ref[i] = y[i]; + } + } + Ok(()) + })) + } +} + +struct CustomOpTwo; + +impl Operator for CustomOpTwo { + fn name(&self) -> &str { + "CustomOpTwo" + } + fn inputs(&self) -> Vec { + vec![OperatorInput::required(TensorElementType::Float32)] + } + + fn outputs(&self) -> Vec { + vec![OperatorOutput::required(TensorElementType::Int32)] + } + + fn create_kernel(&self, _: &KernelAttributes) -> ort::Result> { + Ok(Box::new(|ctx: &KernelContext| { + let x = ctx.input(0)?.unwrap(); + let (x_shape, x) = x.try_extract_tensor::()?; + let mut z = ctx.output(0, x_shape.to_vec())?.unwrap(); + let (_, z_ref) = z.try_extract_tensor_mut::()?; + for i in 0..x_shape.iter().copied().reduce(|acc, e| acc * e).unwrap() as usize { + z_ref[i] = (x[i] * i as f32) as i32; + } + Ok(()) + })) + } +} + +fn main() -> ort::Result<()> { + let _env = ort::init().with_execution_providers([CPUExecutionProvider::default().build()]).commit()?; + + let mut session = Session::builder()? + .with_operators(OperatorDomain::new("test.customop")?.add(CustomOpOne)?.add(CustomOpTwo)?)? + .commit_from_file("tests/data/custom_op_test.onnx")?; + + let allocator = Allocator::new(&session, MemoryInfo::new(AllocationDevice::CPU, 0, AllocatorType::Device, MemoryType::Default)?.clone())?; + + let mut value1 = Tensor::::new(&allocator, [3, 5])?; + { + let (_, data) = value1.extract_tensor_mut(); + for datum in data { + *datum = 0.; + } + } + let mut value2 = Tensor::::new(&allocator, [3, 5])?; + { + let (_, data) = value2.extract_tensor_mut(); + for datum in data { + *datum = 1.; + } + } + { + let values = session.run(ort::inputs![&value1, &value2])?; + let _ = values[0].try_extract_array::()?; + } + + { + let _ = session.run(ort::inputs!["HyperSuperUltraLongInputNameLikeAReallyLongNameSoLongInFactThatItDoesntFitOnTheStackAsSpecifiedInTheSTACK_CSTR_ARRAY_MAX_TOTAL_ConstantDefinedInUtilDotRsThisStringIsSoLongThatImStartingToRunOutOfThingsToSaySoIllJustPutZeros000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000hi0000000000000000000000000000000000000000000000000000000000000000000000000000000" => &value1]); + let _ = session.run(ort::inputs![ + "input1" => &value1, + "input2" => &value1, + "input3" => &value1, + "input4" => &value1, + "input5" => &value1, + "input6" => &value1, + "input7" => &value1, + "input8" => &value1, + "input9" => &value1, + "input10" => &value1, + "input11" => &value1, + "input12" => &value1, + "input_more_than_STACK_CSTR_ARRAY_MAX_ELEMENTS" => &value1, + ]); + } + + { + let adapter = Adapter::from_file("tests/data/adapter.orl", None)?; + let mut options = RunOptions::new()?; + options.add_adapter(&adapter)?; + + drop(adapter); + + let _ = session.run_with_options( + ort::inputs![ + "phony" => &value1 + ], + &options + ); + } + + { + let metadata = session.metadata()?; + + let _ = metadata.custom_keys(); + let _ = metadata.description(); + let _ = metadata.domain(); + let _ = metadata.graph_description(); + let _ = metadata.name(); + let _ = metadata.producer(); + let _ = metadata.version(); + } + + { + let mut binding = session.create_binding()?; + binding.bind_input("input_1", &value1)?; + binding.bind_input("input_2", &value2)?; + binding.bind_output_to_device("output", &Allocator::default().memory_info())?; + let _ = session.run_binding(&binding)?; + } + + Ok(()) +}