#[cfg(feature = "media")] use mcai_worker_sdk::MessageError; #[cfg(feature = "media")] use py_mcai_worker_sdk::python::*; use py_mcai_worker_sdk::{helpers::*, parameters::*}; use pyo3::{prelude::*, types::*}; use serde_json::Value; use std::collections::HashMap; #[test] pub fn test_py_err_to_string() { let gil = Python::acquire_gil(); let py = gil.python(); PyErr::new::("Error message").restore(py); let py_err = PyErr::fetch(py); let expected_message = "TypeError(\'Error message\'".to_string(); assert!(py_err_to_string(py, py_err).contains(&expected_message)); } #[test] pub fn test_py_json_schema_from_type() { Python::with_gil(|py| { let json = py.import("json").unwrap(); let schema = py.import("strong_typing.schema").unwrap(); let locals = [("json", json), ("schema", schema)].into_py_dict(py); let schema: String = py .eval( "json.dumps(schema.classdef_to_schema(dict))", None, Some(locals), ) .unwrap() .extract() .unwrap(); assert!(schema.starts_with("{\"$schema\": \"https://json-schema.org/draft/2020-12/schema\", \"type\": \"object\", \"title\": \"dict")); }); } #[test] pub fn test_get_destination_paths() { let destination_paths = vec![ "/path/to/destination/file_1".to_string(), "/path/to/destination/file_2".to_string(), "/path/to/destination/file_3".to_string(), ]; let gil = Python::acquire_gil(); let py = gil.python(); let py_list = PyList::new(py, destination_paths.clone()); let py_dict = PyDict::new(py); let result = py_dict.set_item("destination_paths", py_list); assert!(result.is_ok()); let py_any: &PyAny = py_dict.into(); let result = get_destination_paths(py_any); assert!(result.is_some()); assert_eq!(destination_paths, result.unwrap()); } #[test] pub fn test_get_destination_paths_without_key() { let gil = Python::acquire_gil(); let py = gil.python(); let py_dict = PyDict::new(py); let py_any: &PyAny = py_dict.into(); let result = get_destination_paths(py_any); assert!(result.is_none()); } #[test] pub fn test_get_destination_paths_without_list_value() { let gil = Python::acquire_gil(); let py = gil.python(); let py_dict = PyDict::new(py); let result = py_dict.set_item("destination_paths", "some_value"); assert!(result.is_ok()); let py_any: &PyAny = py_dict.into(); let result = get_destination_paths(py_any); assert!(result.is_none()); } #[test] #[cfg(feature = "media")] pub fn test_get_stream_indexes() { let gil = Python::acquire_gil(); let py = gil.python(); // whatever the type, since the vec is empty... let filter_list = PyList::new(py, Vec::::new()); let stream_indexes = vec![ StreamDescriptorHandler::new_video_stream(0, filter_list), StreamDescriptorHandler::new_audio_stream(1, filter_list), ]; let py_list: PyObject = stream_indexes.into_py(py); let py_any: &PyAny = py_list.cast_as(py).unwrap(); let result = get_stream_descriptors(py_any); assert!(result.is_ok()); let result = result.unwrap(); assert_eq!(2, result.len()); } #[test] #[cfg(feature = "media")] pub fn test_get_stream_indexes_without_list() { let gil = Python::acquire_gil(); let py = gil.python(); let py_string = PyString::new(py, "this_is_not_a_list!"); let py_any: &PyAny = py_string.into(); let expected_error = MessageError::RuntimeError( "unable to access init_process(..) python response: PyDowncastError { from: \'this_is_not_a_list!\', to: \"PyList\" }".to_string(), ); let result = get_stream_descriptors(py_any); assert!(result.is_err()); assert_eq!(expected_error, result.unwrap_err()); } #[test] pub fn test_get_worker_parameters_schema() { let parameters_schema = get_parameters_schema(); let expected = "{\ \"$schema\": \"https://json-schema.org/draft/2020-12/schema\", \ \"type\": \"object\", \ \"properties\": {\ \"source_path\": {\"type\": \"string\"}, \ \"destination_path\": {\"type\": \"string\"}}, \ \"additionalProperties\": false, \ \"required\": [\"source_path\"]\ }" .to_string(); assert_eq!(parameters_schema, expected); } #[test] pub fn test_has_worker_method() { let gil = Python::acquire_gil(); let (_py, python_module) = get_python_module(&gil).unwrap(); assert!(has_worker_method(python_module, "init")); } #[test] pub fn test_build_parameters() { let mut parameters = HashMap::::new(); parameters.insert( "string_parameter".to_string(), Value::String("string_value".to_string()), ); parameters.insert("null_parameter".to_string(), Value::Null); parameters.insert("boolean_parameter".to_string(), Value::Bool(true)); parameters.insert( "number_parameter".to_string(), Value::Number(serde_json::Number::from(123)), ); parameters.insert( "array_of_string_parameter".to_string(), Value::Array(vec![Value::String("string_value".to_string())]), ); parameters.insert( "array_of_null_parameter".to_string(), Value::Array(vec![Value::Null]), ); parameters.insert( "array_of_bool_parameter".to_string(), Value::Array(vec![Value::Bool(true)]), ); parameters.insert( "array_of_number_parameter".to_string(), Value::Array(vec![Value::Number(serde_json::Number::from(123))]), ); let worker_parameters = PythonWorkerParameters { parameters }; let gil = Python::acquire_gil(); let py = gil.python(); let result = build_parameters(worker_parameters, py); assert!(result.is_ok()); let py_parameters = result.unwrap(); assert!(py_parameters.get_item("string_parameter").is_some()); assert!(py_parameters.get_item("boolean_parameter").is_some()); assert!(py_parameters.get_item("number_parameter").is_some()); assert!(py_parameters .get_item("array_of_string_parameter") .is_some()); assert!(py_parameters.get_item("array_of_null_parameter").is_some()); assert!(py_parameters.get_item("array_of_bool_parameter").is_some()); assert!(py_parameters .get_item("array_of_number_parameter") .is_some()); assert!(py_parameters.get_item("null_parameter").is_none()); } #[test] pub fn test_build_parameters_with_object_value() { let mut parameters = HashMap::::new(); let parameter_key = "object_parameter".to_string(); parameters.insert( parameter_key.clone(), Value::Object(serde_json::Map::::new()), ); let worker_parameters = PythonWorkerParameters { parameters }; let gil = Python::acquire_gil(); let py = gil.python(); let result = build_parameters(worker_parameters, py); assert!(result.is_ok()); let reference = PyDict::new(py); reference.set_item(parameter_key, PyDict::new(py)).unwrap(); assert_eq!( core::cmp::Ordering::Equal, result.unwrap().compare(reference).unwrap() ); } #[test] pub fn test_build_parameters_for_requirements() { use serde_json::json; let mut parameters = HashMap::::new(); let parameter_key = "requirements".to_string(); let value = json!({ "paths": [] }); parameters.insert(parameter_key.clone(), value); let worker_parameters = PythonWorkerParameters { parameters }; let gil = Python::acquire_gil(); let py = gil.python(); let result = build_parameters(worker_parameters, py); assert!(result.is_ok()); let reference = PyDict::new(py); let requirement_content = PyDict::new(py); requirement_content .set_item("paths", PyList::empty(py)) .unwrap(); reference .set_item(parameter_key, requirement_content) .unwrap(); assert_eq!( core::cmp::Ordering::Equal, result.unwrap().compare(reference).unwrap() ); } #[test] pub fn test_build_parameters_with_array_of_array_value() { let mut parameters = HashMap::::new(); let parameter_key = "array_of_array_parameter".to_string(); parameters.insert( parameter_key.clone(), Value::Array(vec![Value::Array(vec![Value::Bool(true)])]), ); let worker_parameters = PythonWorkerParameters { parameters }; let gil = Python::acquire_gil(); let py = gil.python(); let result = build_parameters(worker_parameters, py); let reference = PyDict::new(py); let content = PyList::empty(py); let sub_content = PyList::empty(py); sub_content.append(PyBool::new(py, true)).unwrap(); content.append(sub_content).unwrap(); reference.set_item(parameter_key, content).unwrap(); assert_eq!( core::cmp::Ordering::Equal, result.unwrap().compare(reference).unwrap() ); } #[test] pub fn test_build_parameters_with_array_of_object_value() { let mut parameters = HashMap::::new(); let parameter_key = "array_of_object_parameter".to_string(); parameters.insert( parameter_key.clone(), Value::Array(vec![Value::Object(serde_json::Map::::new())]), ); let worker_parameters = PythonWorkerParameters { parameters }; let gil = Python::acquire_gil(); let py = gil.python(); let result = build_parameters(worker_parameters, py); let reference = PyDict::new(py); let content = PyList::empty(py); content.append(PyDict::new(py)).unwrap(); reference.set_item(parameter_key, content).unwrap(); assert_eq!( core::cmp::Ordering::Equal, result.unwrap().compare(reference).unwrap() ); }