tmc_langs_r/
r_run_result.rs

1//! Struct modeling the test run results from R.
2
3use serde::{Deserialize, Serialize};
4use std::{collections::HashMap, fmt::Write};
5use tmc_langs_framework::{RunResult, RunStatus, TestResult};
6
7#[derive(Debug, Deserialize, Serialize)]
8#[serde(rename_all = "camelCase")]
9pub struct RRunResult {
10    run_status: RRunStatus,
11    backtrace: Vec<String>,
12    test_results: Vec<RTestResult>,
13}
14
15impl From<RRunResult> for RunResult {
16    fn from(r_run_result: RRunResult) -> RunResult {
17        let mut logs = HashMap::new();
18        if !r_run_result.backtrace.is_empty() {
19            logs.insert(
20                "compiler_output".to_string(),
21                r_run_result
22                    .backtrace
23                    .into_iter()
24                    .fold(String::new(), |mut output, s| {
25                        let _ = writeln!(output, "{s}");
26                        output
27                    }),
28            );
29        }
30        let status = match r_run_result.run_status {
31            RRunStatus::Success => {
32                // check test results to determine the status
33                let mut status = RunStatus::Passed;
34                for test_result in &r_run_result.test_results {
35                    if test_result.status != RTestStatus::Pass {
36                        status = RunStatus::TestsFailed;
37                    }
38                }
39                status
40            }
41            // todo: differentiate between different errors?
42            _ => RunStatus::CompileFailed,
43        };
44
45        RunResult {
46            status,
47            test_results: r_run_result
48                .test_results
49                .into_iter()
50                .map(|t| t.into())
51                .collect(),
52            logs,
53        }
54    }
55}
56
57#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
58#[serde(rename_all = "snake_case")]
59enum RRunStatus {
60    Success,
61    RunFailed,
62    SourcingFailed,
63}
64
65#[derive(Debug, Deserialize, Serialize)]
66#[serde(rename_all = "lowercase")]
67struct RTestResult {
68    status: RTestStatus,
69    name: String,
70    message: String,
71    backtrace: Vec<String>,
72    points: Vec<String>,
73}
74
75impl From<RTestResult> for TestResult {
76    fn from(r_test_result: RTestResult) -> TestResult {
77        TestResult {
78            name: r_test_result.name,
79            successful: r_test_result.status == RTestStatus::Pass,
80            points: r_test_result.points,
81            message: r_test_result.message,
82            exception: r_test_result.backtrace,
83        }
84    }
85}
86
87#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
88#[serde(rename_all = "lowercase")]
89enum RTestStatus {
90    Pass,
91    Fail,
92}
93
94#[cfg(test)]
95mod test {
96    use super::*;
97
98    fn init() {
99        use log::*;
100        use simple_logger::*;
101        let _ = SimpleLogger::new().with_level(LevelFilter::Debug).init();
102    }
103
104    #[test]
105    fn converts() {
106        init();
107
108        let r_run_result = RRunResult {
109            run_status: RRunStatus::Success,
110            test_results: vec![],
111            backtrace: vec![],
112        };
113        let run_result: RunResult = r_run_result.into();
114        assert_eq!(run_result.status, RunStatus::Passed);
115    }
116}