Skip to content
This repository was archived by the owner on Oct 24, 2024. It is now read-only.

Commit c9e20c3

Browse files
committed
feat: rewrite how test cases are stored
Instead of creating separate models for each test case data type, we will store them all in a string and let the data decide how to work with it. However, this method will result in us losing the ability to do strict output comparisons (we have implemented only string based output correctness checking). I do not think I am willing to give up such a big feature for a little ease of db schema. However I will keep this in commit history so that I can reference it later down the line.
1 parent fe8d792 commit c9e20c3

25 files changed

+92
-414
lines changed

apps/orchestrator/src/learning/dto/mutations/create_question.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use edgedb_derive::Queryable;
44
use utilities::graphql::ApiError;
55
use uuid::Uuid;
66

7-
use crate::learning::dto::queries::test_case::TestCase;
7+
use crate::learning::dto::queries::test_case::TestCaseInput;
88

99
/// The input object used to create a new question
1010
#[derive(Debug, InputObject, Getters)]
@@ -19,7 +19,7 @@ pub struct CreateQuestionInput {
1919
class_ids: Vec<Uuid>,
2020

2121
/// All the test cases that are related to this question
22-
test_cases: Vec<TestCase>,
22+
test_cases: Vec<TestCaseInput>,
2323
}
2424

2525
/// The result type if the question was created successfully

apps/orchestrator/src/learning/dto/queries/question_details.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,34 @@ use serde::Deserialize;
33
use utilities::graphql::ApiError;
44
use uuid::Uuid;
55

6-
use super::test_case::TestCaseUnit;
7-
8-
#[derive(SimpleObject, Deserialize)]
6+
#[derive(Debug, SimpleObject, Deserialize)]
97
pub struct AuthoredByProfile {
108
username: String,
119
}
1210

13-
#[derive(SimpleObject, Deserialize)]
11+
#[derive(Debug, SimpleObject, Deserialize)]
1412
pub struct AuthoredByInformation {
1513
profile: AuthoredByProfile,
1614
}
1715

1816
#[derive(Debug, SimpleObject, Deserialize)]
1917
pub struct TestCaseData {
20-
pub unit_type: TestCaseUnit,
21-
pub string_value: Option<String>,
22-
pub string_collection_value: Option<Vec<String>>,
23-
pub number_value: Option<f64>,
24-
pub number_collection_value: Option<Vec<f64>>,
25-
}
26-
27-
#[derive(Debug, SimpleObject, Deserialize)]
28-
pub struct QuestionData {
29-
/// The data related to this input
30-
pub data: TestCaseData,
18+
/// The actual data associated with the input/output
19+
pub data: String,
3120
}
3221

3322
#[derive(Debug, SimpleObject, Deserialize)]
3423
pub struct QuestionTestCase {
3524
/// The unique ID for this test case
36-
id: Uuid,
25+
pub id: Uuid,
3726
/// The ordered inputs for this test case
38-
pub inputs: Vec<QuestionData>,
27+
pub inputs: Vec<TestCaseData>,
3928
/// The ordered outputs for this test case
40-
pub outputs: Vec<QuestionData>,
29+
pub outputs: Vec<TestCaseData>,
4130
}
4231

4332
/// The input object used to get details about a question
44-
#[derive(SimpleObject, Deserialize)]
33+
#[derive(Debug, SimpleObject, Deserialize)]
4534
pub struct QuestionDetailsOutput {
4635
/// The name/title of the question
4736
pub name: String,
@@ -63,7 +52,7 @@ pub struct QuestionDetailsOutput {
6352
}
6453

6554
/// The output object when creating a new question
66-
#[derive(Union)]
55+
#[derive(Debug, Union)]
6756
pub enum QuestionDetailsResultUnion {
6857
/// The type returned when getting details about a question was successful
6958
Result(QuestionDetailsOutput),
Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,15 @@
1-
use async_graphql::{Enum, InputObject, SimpleObject};
2-
use main_db::ToEdgeqlString;
3-
use serde::{Deserialize, Serialize};
4-
use strum::EnumIter;
5-
6-
#[derive(Enum, Copy, Clone, Eq, PartialEq, Debug, EnumIter, Deserialize, Serialize)]
7-
pub enum TestCaseUnit {
8-
#[serde(rename = "NumberUnit")]
9-
Number,
10-
#[serde(rename = "StringUnit")]
11-
String,
12-
#[serde(rename = "NumberCollectionUnit")]
13-
NumberCollection,
14-
#[serde(rename = "StringCollectionUnit")]
15-
StringCollection,
16-
}
17-
18-
impl ToEdgeqlString for TestCaseUnit {
19-
fn get_module_name() -> String {
20-
"learning".to_string()
21-
}
22-
}
23-
24-
#[derive(Debug, SimpleObject, InputObject)]
25-
pub struct InputCaseUnit {
26-
pub data_type: TestCaseUnit,
27-
pub data: String,
28-
/// The name of the variable to store it as
29-
pub name: String,
30-
}
1+
use async_graphql::{InputObject, SimpleObject};
312

323
#[derive(Debug, SimpleObject, InputObject)]
33-
pub struct OutputCaseUnit {
34-
/// The type of data to store this line as
35-
pub data_type: TestCaseUnit,
4+
pub struct TestCaseDataInput {
365
/// The data to store
376
pub data: String,
387
}
398

409
#[derive(Debug, SimpleObject, InputObject)]
41-
pub struct TestCase {
10+
pub struct TestCaseInput {
4211
/// The inputs related to this test case
43-
pub inputs: Vec<InputCaseUnit>,
12+
pub inputs: Vec<TestCaseDataInput>,
4413
/// The outputs related to this test case
45-
pub outputs: Vec<OutputCaseUnit>,
14+
pub outputs: Vec<TestCaseDataInput>,
4615
}

apps/orchestrator/src/learning/resolver.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use super::{
99
},
1010
queries::{
1111
class_details::ClassDetailsResultUnion, question_details::QuestionDetailsResultUnion,
12-
test_case::TestCaseUnit,
1312
},
1413
},
1514
service::{LearningService, LearningServiceTrait},
@@ -30,11 +29,6 @@ pub struct LearningMutation {}
3029

3130
#[Object]
3231
impl LearningQuery {
33-
/// Get all the types of test case units possible
34-
async fn test_case_units(&self, ctx: &Context<'_>) -> Vec<TestCaseUnit> {
35-
ctx.data_unchecked::<LearningService>().test_case_units()
36-
}
37-
3832
/// Get information about a class
3933
async fn class_details(
4034
&self,

apps/orchestrator/src/learning/service.rs

Lines changed: 21 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ use super::dto::{
55
execute_code_for_question::{ExecuteCodeForQuestionOutput, TestCaseStatus},
66
},
77
queries::{
8-
class_details::ClassDetailsOutput,
9-
question_details::QuestionDetailsOutput,
10-
test_case::{TestCase, TestCaseUnit},
8+
class_details::ClassDetailsOutput, question_details::QuestionDetailsOutput,
9+
test_case::TestCaseInput,
1110
},
1211
};
13-
use crate::{
14-
farem::{
15-
dto::mutations::execute_code::{ExecuteCodeError, ExecuteCodeErrorStep},
16-
service::{FaremService, SupportedLanguage},
17-
},
18-
utils::case_unit_to_argument,
12+
use crate::farem::{
13+
dto::mutations::execute_code::{ExecuteCodeError, ExecuteCodeErrorStep},
14+
service::{FaremService, SupportedLanguage},
1915
};
2016
use async_trait::async_trait;
2117
use auth::validate_user_role;
@@ -24,7 +20,6 @@ use edgedb_tokio::Client as DbClient;
2420
use rand::{distributions::Alphanumeric, Rng};
2521
use slug::slugify;
2622
use std::sync::Arc;
27-
use strum::IntoEnumIterator;
2823
use utilities::{graphql::ApiError, models::IdObject, users::AccountType};
2924
use uuid::Uuid;
3025

@@ -38,29 +33,16 @@ const CREATE_CLASS: &str =
3833
include_str!("../../../../libs/main-db/edgeql/learning/create-class.edgeql");
3934
const CREATE_QUESTION: &str =
4035
include_str!("../../../../libs/main-db/edgeql/learning/create-question.edgeql");
41-
const INSERT_NUMBER_COLLECTION_UNIT: &str = include_str!(
42-
"../../../../libs/main-db/edgeql/learning/test-cases/number-collection-unit.edgeql"
43-
);
44-
const INSERT_NUMBER_UNIT: &str =
45-
include_str!("../../../../libs/main-db/edgeql/learning/test-cases/number-unit.edgeql");
46-
const INSERT_STRING_UNIT: &str =
47-
include_str!("../../../../libs/main-db/edgeql/learning/test-cases/string-unit.edgeql");
48-
const INSERT_STRING_COLLECTION_UNIT: &str = include_str!(
49-
"../../../../libs/main-db/edgeql/learning/test-cases/string-collection-unit.edgeql"
36+
const INSERT_TEST_CASE_DATA: &str = include_str!(
37+
"../../../../libs/main-db/edgeql/learning/test-cases/insert-test-case-data.edgeql"
5038
);
51-
const INSERT_INPUT_CASE_UNIT: &str =
52-
include_str!("../../../../libs/main-db/edgeql/learning/test-cases/input-case-unit.edgeql");
53-
const INSERT_OUTPUT_CASE_UNIT: &str =
54-
include_str!("../../../../libs/main-db/edgeql/learning/test-cases/output-case-unit.edgeql");
5539
const INSERT_TEST_CASE: &str =
5640
include_str!("../../../../libs/main-db/edgeql/learning/test-cases/test-case.edgeql");
5741
const UPDATE_QUESTION: &str =
5842
include_str!("../../../../libs/main-db/edgeql/learning/test-cases/update-question.edgeql");
5943

6044
#[async_trait]
6145
pub trait LearningServiceTrait: Sync + Send {
62-
fn test_case_units(&self) -> Vec<TestCaseUnit>;
63-
6446
async fn class_details<'a>(&self, class_id: Uuid) -> Result<ClassDetailsOutput, ApiError>;
6547

6648
async fn question_details<'a>(
@@ -82,7 +64,7 @@ pub trait LearningServiceTrait: Sync + Send {
8264
account_type: &AccountType,
8365
name: &'a str,
8466
problem: &'a str,
85-
test_cases: &[TestCase],
67+
test_cases: &[TestCaseInput],
8668
class_ids: &[Uuid],
8769
) -> Result<CreateQuestionOutput, ApiError>;
8870

@@ -112,10 +94,6 @@ impl LearningService {}
11294

11395
#[async_trait]
11496
impl LearningServiceTrait for LearningService {
115-
fn test_case_units(&self) -> Vec<TestCaseUnit> {
116-
TestCaseUnit::iter().collect()
117-
}
118-
11997
async fn class_details<'a>(&self, class_id: Uuid) -> Result<ClassDetailsOutput, ApiError> {
12098
self.db_conn
12199
.query_required_single::<ClassDetailsOutput, _>(CLASS_DETAILS, &(class_id,))
@@ -169,7 +147,7 @@ impl LearningServiceTrait for LearningService {
169147
account_type: &AccountType,
170148
name: &'a str,
171149
problem: &'a str,
172-
test_cases: &[TestCase],
150+
test_cases: &[TestCaseInput],
173151
class_ids: &[Uuid],
174152
) -> Result<CreateQuestionOutput, ApiError> {
175153
validate_user_role(&AccountType::Teacher, account_type)?;
@@ -216,47 +194,27 @@ impl LearningServiceTrait for LearningService {
216194
.to_string(),
217195
}
218196
})?;
219-
fn get_insert_ql(test_case: &TestCaseUnit) -> &'static str {
220-
match test_case {
221-
TestCaseUnit::Number => INSERT_NUMBER_UNIT,
222-
TestCaseUnit::NumberCollection => INSERT_NUMBER_COLLECTION_UNIT,
223-
TestCaseUnit::String => INSERT_STRING_UNIT,
224-
TestCaseUnit::StringCollection => INSERT_STRING_COLLECTION_UNIT,
225-
}
226-
}
227197
let mut test_cases_to_associate = vec![];
228198
for test_case in test_cases.iter() {
229199
let mut input_case_units = vec![];
230200
let mut output_case_units = vec![];
231201
for (idx, input) in test_case.inputs.iter().enumerate() {
232-
let insert_ql = get_insert_ql(&input.data_type);
233-
let case_unit = self
234-
.db_conn
235-
.query_required_single::<IdObject, _>(insert_ql, &(&input.data,))
236-
.await
237-
.unwrap();
238202
let input_case_unit = self
239203
.db_conn
240204
.query_required_single::<IdObject, _>(
241-
INSERT_INPUT_CASE_UNIT,
242-
&(&input.name, idx as i32, case_unit.id),
205+
INSERT_TEST_CASE_DATA,
206+
&(idx as i32, input.data.clone()),
243207
)
244208
.await
245209
.unwrap();
246210
input_case_units.push(input_case_unit.id);
247211
}
248212
for (idx, output) in test_case.outputs.iter().enumerate() {
249-
let insert_ql = get_insert_ql(&output.data_type);
250-
let case_unit = self
251-
.db_conn
252-
.query_required_single::<IdObject, _>(insert_ql, &(&output.data,))
253-
.await
254-
.unwrap();
255213
let output_case_unit = self
256214
.db_conn
257215
.query_required_single::<IdObject, _>(
258-
INSERT_OUTPUT_CASE_UNIT,
259-
&(idx as i32, case_unit.id),
216+
INSERT_TEST_CASE_DATA,
217+
&(idx as i32, output.data.clone()),
260218
)
261219
.await
262220
.unwrap();
@@ -306,7 +264,7 @@ impl LearningServiceTrait for LearningService {
306264
let arguments = test_case
307265
.inputs
308266
.iter()
309-
.map(case_unit_to_argument)
267+
.map(|f| f.data.clone())
310268
.collect::<Vec<_>>();
311269
let user_output = self
312270
.farem_service
@@ -316,13 +274,15 @@ impl LearningServiceTrait for LearningService {
316274
error: f,
317275
step: ExecuteCodeErrorStep::WasmExecution,
318276
})?;
319-
let expected_output = test_case
277+
let collected_expected_output = test_case
320278
.outputs
321279
.iter()
322-
.map(case_unit_to_argument)
323-
.collect::<Vec<_>>()
324-
.join("\n")
325-
+ "\n";
280+
.map(|f| f.data.clone())
281+
.collect::<Vec<_>>();
282+
let mut expected_output = collected_expected_output.join("\n");
283+
if !collected_expected_output.is_empty() {
284+
expected_output += "\n";
285+
}
326286
outputs.push(TestCaseStatus {
327287
passed: user_output == expected_output,
328288
user_output,

apps/orchestrator/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ pub mod farem;
22
pub mod graphql;
33
pub mod learning;
44
pub mod users;
5-
pub mod utils;
65

76
use anyhow::Result;
87
use config::JwtConfig;

apps/orchestrator/src/utils.rs

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)