Skip to main content

runmat_runtime/testing/
objects.rs

1use runmat_test::descriptor::{FixtureDescriptor, TestDescriptor};
2use runmat_test::result::{Diagnostic, TestResult};
3use runmat_value::{ObjectArray, ObjectInstance, Value};
4
5pub const TEST_CASE_CLASS: &str = "matlab.unittest.TestCase";
6pub const FUNCTION_TEST_CASE_CLASS: &str = "matlab.unittest.FunctionTestCase";
7pub const TEST_SUITE_CLASS: &str = "matlab.unittest.TestSuite";
8pub const TEST_RESULT_CLASS: &str = "matlab.unittest.TestResult";
9
10pub fn test_case_object(name: impl Into<String>, function_based: bool) -> Value {
11    let mut object = ObjectInstance::new(
12        if function_based {
13            FUNCTION_TEST_CASE_CLASS
14        } else {
15            TEST_CASE_CLASS
16        }
17        .into(),
18    );
19    object
20        .properties
21        .insert("Name".into(), Value::String(name.into()));
22    Value::Object(object)
23}
24
25pub fn test_suite_object(test: &TestDescriptor) -> Value {
26    let mut object = ObjectInstance::new(TEST_SUITE_CLASS.into());
27    object
28        .properties
29        .insert("Name".into(), Value::String(test.display_name.clone()));
30    object.properties.insert(
31        "ProcedureName".into(),
32        Value::String(
33            test.procedure
34                .display_name
35                .rsplit('/')
36                .next()
37                .unwrap_or(test.procedure.display_name.as_str())
38                .to_owned(),
39        ),
40    );
41    object.properties.insert(
42        "TestFile".into(),
43        Value::String(test.procedure.source.relative_path.clone()),
44    );
45    object.properties.insert(
46        "Tags".into(),
47        Value::StringArray(
48            runmat_value::StringArray::new(test.tags.clone(), vec![1, test.tags.len()])
49                .expect("test tags have a valid row shape"),
50        ),
51    );
52    object.properties.insert(
53        "__runmat_test_id".into(),
54        Value::String(test.id.as_str().into()),
55    );
56    Value::Object(object)
57}
58
59pub fn test_result_object(name: impl Into<String>, result: &TestResult) -> Value {
60    let mut object = ObjectInstance::new(TEST_RESULT_CLASS.into());
61    object
62        .properties
63        .insert("Name".into(), Value::String(name.into()));
64    object
65        .properties
66        .insert("Passed".into(), Value::Bool(result.state.is_success()));
67    object
68        .properties
69        .insert("Failed".into(), Value::Bool(result.state.failed));
70    object
71        .properties
72        .insert("Incomplete".into(), Value::Bool(result.state.incomplete));
73    object
74        .properties
75        .insert("Flaky".into(), Value::Bool(result.flaky));
76    object.properties.insert(
77        "Details".into(),
78        Value::String(
79            result
80                .attempts
81                .last()
82                .map(|attempt| attempt.output.clone())
83                .unwrap_or_default(),
84        ),
85    );
86    object.properties.insert(
87        "__runmat_test_id".into(),
88        Value::String(result.test_id.as_str().into()),
89    );
90    Value::Object(object)
91}
92
93pub fn fixture_object(fixture: &FixtureDescriptor) -> Value {
94    let mut object = ObjectInstance::new("matlab.unittest.fixtures.Fixture".into());
95    object
96        .properties
97        .insert("Name".into(), Value::String(fixture.display_name.clone()));
98    object.properties.insert(
99        "__runmat_fixture_id".into(),
100        Value::String(fixture.id.as_str().into()),
101    );
102    Value::Object(object)
103}
104
105pub fn diagnostic_object(diagnostic: &Diagnostic) -> Value {
106    let mut object = ObjectInstance::new("matlab.unittest.diagnostics.Diagnostic".into());
107    object.properties.insert(
108        "Identifier".into(),
109        Value::String(diagnostic.identifier.clone()),
110    );
111    object
112        .properties
113        .insert("Message".into(), Value::String(diagnostic.message.clone()));
114    Value::Object(object)
115}
116
117pub fn plugin_object(class_name: impl Into<String>) -> Value {
118    Value::Object(ObjectInstance::new(class_name.into()))
119}
120
121pub fn object_array_or_scalar(
122    class_name: impl Into<String>,
123    values: Vec<Value>,
124) -> Result<Value, String> {
125    if values.len() == 1 {
126        Ok(values.into_iter().next().expect("one value"))
127    } else {
128        ObjectArray::row(class_name, values).map(Value::ObjectArray)
129    }
130}