Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

standardised format of json rule output #569

Merged
merged 17 commits into from
Jan 19, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
sorting json rule output
Soph1514 committed Jan 6, 2025
commit 705e782b13f5b511b0818ad8d42f07e3221187a7
97 changes: 71 additions & 26 deletions conjure_oxide/src/utils/testing.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ use std::io::Write;
use std::sync::{Arc, RwLock};

use conjure_core::context::Context;
use serde_json::{json, Error as JsonError, Value as JsonValue};
use serde_json::{json, Error as JsonError, Map, Value as JsonValue};

use conjure_core::error::Error;

@@ -191,34 +191,17 @@ pub fn read_rule_trace(
test_name: &str,
prefix: &str,
accept: bool,
) -> Result<Vec<String>, std::io::Error> {
) -> Result<JsonValue, anyhow::Error> {
let filename = format!("{path}/{test_name}-{prefix}-rule-trace.json");
let mut rules_trace: Vec<String> = read_to_string(&filename)
.unwrap()
.lines()
.map(String::from)
.collect();

//only count the number of rule in generated file (assumming the expected version already has that line and it is correct)
if prefix == "generated" {
let rule_count = rules_trace.len();

let count_message = json!({
"message": " Number of rules applied",
"count": rule_count
});

// Append the count message to the vector
let count_message_string = serde_json::to_string(&count_message)?;
rules_trace.push(count_message_string.clone());
let rule_traces: JsonValue;

// Write the updated rules trace back to the file
let mut file = OpenOptions::new()
.write(true)
.truncate(true) // Overwrite the file with updated content
.open(&filename)?;
if prefix == "expected" {
rule_traces = count_and_sort_rules(&filename)?;
} else {
let file_contents = std::fs::read_to_string(&filename)?;

writeln!(file, "{}", rules_trace.join("\n"))?;
rule_traces = sort_json_object(&serde_json::from_str(&file_contents)?, false);
}

if accept {
@@ -228,7 +211,69 @@ pub fn read_rule_trace(
)?;
}

Ok(rules_trace)
Ok(rule_traces)
}

pub fn count_and_sort_rules(filename: &str) -> Result<JsonValue, anyhow::Error> {
let file_contents = read_to_string(&filename)?;
let mut sorted_json_rules = JsonValue::Null;

if file_contents.trim().is_empty() {
let rule_count_message = json!({
"Number of rules applied": 0,
});

sorted_json_rules = sort_json_object(&rule_count_message, true);
} else {
let rule_count = file_contents.lines().count();
sorted_json_rules = sort_json_rules(&file_contents);

// Add the rule count message to the sorted rules
let rule_count_message = json!({
"Number of rules applied": rule_count,
});

if let Some(array) = sorted_json_rules.as_array_mut() {
array.push(sort_json_object(&rule_count_message, false));
} else {
return Err(anyhow::anyhow!("Expected JSON array, but found something else").into());
}
}

// Serialize the sorted JSON back to a string
let generated_sorted_json_rules = serde_json::to_string_pretty(&sorted_json_rules)?;

// Write the sorted JSON back to the file
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.open(filename)?;

file.write_all(generated_sorted_json_rules.as_bytes())?;

Ok(sorted_json_rules)
}

fn sort_json_rules(json_rule_traces: &str) -> JsonValue {
let mut sorted_rule_traces = Vec::new();

for line in json_rule_traces.lines() {
let mut map = Map::new();

let parts = line.split("; ");

for part in parts {
if let Some((key, value)) = part.split_once(": ") {
map.insert(
key.trim().to_string(),
json!(value.trim().trim_end_matches("\"}}")),
);
}
}

sorted_rule_traces.push(JsonValue::Object(map));
}
JsonValue::Array(sorted_rule_traces)
}

pub fn read_human_rule_trace(
29 changes: 15 additions & 14 deletions conjure_oxide/tests/generated_tests.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use conjure_core::rule_engine::rewrite_naive;
use conjure_oxide::utils::essence_parser::parse_essence_file_native;
use conjure_oxide::utils::testing::read_human_rule_trace;
use conjure_oxide::utils::testing::{read_human_rule_trace, read_rule_trace};
use glob::glob;
use itertools::Itertools;
use std::collections::BTreeMap;
use std::env;
use std::error::Error;
use std::fs;
use std::fs::File;
use tracing::{span, Level};
use tracing::{span, Level, Metadata as OtherMetadata};
use tracing_subscriber::{
filter::EnvFilter, filter::FilterFn, fmt, layer::SubscriberExt, Layer, Registry,
};
@@ -34,7 +34,7 @@ use conjure_oxide::utils::testing::save_stats_json;
use conjure_oxide::utils::testing::{
read_minion_solutions_json, read_model_json, save_minion_solutions_json, save_model_json,
};
use conjure_oxide::SolverFamily;
use conjure_oxide::{Metadata, SolverFamily};
use serde::Deserialize;

use pretty_assertions::assert_eq;
@@ -234,14 +234,14 @@ fn integration_test_inner(
}

//Stage 4: Check that the generated rules match with the expected in temrs if type, order and count
// let generated_rule_trace = read_rule_trace(path, essence_base, "generated", accept)?;
// let expected_rule_trace = read_rule_trace(path, essence_base, "expected", accept)?;
let generated_rule_trace = read_rule_trace(path, essence_base, "generated", accept)?;
let expected_rule_trace = read_rule_trace(path, essence_base, "expected", accept)?;

let generated_rule_trace_human =
read_human_rule_trace(path, essence_base, "generated", accept)?;
let expected_rule_trace_human = read_human_rule_trace(path, essence_base, "expected", accept)?;

//assert_eq!(expected_rule_trace, generated_rule_trace);
assert_eq!(expected_rule_trace, generated_rule_trace);
assert_eq!(expected_rule_trace_human, generated_rule_trace_human);

// test solutions against conjure before writing
@@ -356,34 +356,35 @@ pub fn create_scoped_subscriber(
impl tracing::Subscriber + Send + Sync,
Vec<tracing_appender::non_blocking::WorkerGuard>,
) {
//let (target1_layer, guard1) = create_file_layer_json(path, test_name);
let (target1_layer, guard1) = create_file_layer_json(path, test_name);
let (target2_layer, guard2) = create_file_layer_human(path, test_name);
let layered = target2_layer;
let layered = target1_layer.and_then(target2_layer);

let subscriber = Arc::new(tracing_subscriber::registry().with(layered))
as Arc<dyn tracing::Subscriber + Send + Sync>;
// setting this subscriber as the default
let _default = tracing::subscriber::set_default(subscriber.clone());

(subscriber, vec![guard2])
(subscriber, vec![guard1, guard2])
}

fn create_file_layer_json(
path: &str,
test_name: &str,
) -> (impl Layer<Registry> + Send + Sync, WorkerGuard) {
let file = File::create(format!("{path}/{test_name}-generated-rule-trace.json"))
let file = File::create(format!("{path}/{test_name}-expected-rule-trace.json"))
.expect("Unable to create log file");
let (non_blocking, guard1) = tracing_appender::non_blocking(file);

let layer1 = fmt::layer()
.with_writer(non_blocking)
.json()
.with_writer(non_blocking)
.with_level(false)
.without_time()
.with_target(false)
.with_filter(EnvFilter::new("rule_engine=trace"))
.with_filter(FilterFn::new(|meta| meta.target() == "rule_engine"));
.without_time()
.with_filter(FilterFn::new(|meta: &OtherMetadata| {
meta.target() == "rule_engine"
}));

(layer1, guard1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Number of rules applied": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Number of rules applied": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Number of rules applied": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Number of rules applied": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[
{
"rule_applied": "div_to_bubble ([(\\\"Bubble\\\", 6000)])",
"initial_expression": "UnsafeDiv(a, b)",
"tranformed_expression": "{SafeDiv(a, b) @ (b != 0)}",
"new_top": "[]"
},
{
"rule_applied": "bubble_up ([(\\\"Bubble\\\", 8900)])",
"initial_expression": "({SafeDiv(a, b) @ (b != 0)} = 1)",
"tranformed_expression": "{(SafeDiv(a, b) = 1) @ And([(b != 0)])}",
"new_top": "[]"
},
{
"rule_applied": "expand_bubble ([(\\\"Bubble\\\", 8900)])",
"initial_expression": "{(SafeDiv(a, b) = 1) @ And([(b != 0)])}",
"tranformed_expression": "And([(SafeDiv(a, b) = 1), And([(b != 0)])])",
"new_top": "[]"
},
{
"rule_applied": "remove_unit_vector_and ([(\\\"Base\\\", 8800)])",
"initial_expression": "And([(b != 0)])",
"tranformed_expression": "(b != 0)",
"new_top": "[]"
},
{
"rule_applied": "introduce_diveq ([(\\\"Minion\\\", 4200)])",
"initial_expression": "(SafeDiv(a, b) = 1)",
"tranformed_expression": "DivEq(a, b, 1)",
"new_top": "[]"
},
{
"Number of rules applied": 5
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"rule_applied": "apply_eval_constant ([(\\\"Constant\\\", 9001)])",
"initial_expression": "UnsafeDiv(4, 2)",
"tranformed_expression": "2",
"new_top": "[]"
},
{
"rule_applied": "geq_to_ineq ([(\\\"Minion\\\", 4100)])",
"initial_expression": "(a >= 2)",
"tranformed_expression": "Ineq(2, a, 0)",
"new_top": "[]"
},
{
"Number of rules applied": 2
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[
{
"rule_applied": "div_to_bubble ([(\\\"Bubble\\\", 6000)])",
"initial_expression": "UnsafeDiv(8, a)",
"tranformed_expression": "{SafeDiv(8, a) @ (a != 0)}",
"new_top": "[]"
},
{
"rule_applied": "bubble_up ([(\\\"Bubble\\\", 8900)])",
"initial_expression": "(2 = {SafeDiv(8, a) @ (a != 0)})",
"tranformed_expression": "{(2 = SafeDiv(8, a)) @ And([(a != 0)])}",
"new_top": "[]"
},
{
"rule_applied": "expand_bubble ([(\\\"Bubble\\\", 8900)])",
"initial_expression": "{(2 = SafeDiv(8, a)) @ And([(a != 0)])}",
"tranformed_expression": "And([(2 = SafeDiv(8, a)), And([(a != 0)])])",
"new_top": "[]"
},
{
"rule_applied": "remove_unit_vector_and ([(\\\"Base\\\", 8800)])",
"initial_expression": "And([(a != 0)])",
"tranformed_expression": "(a != 0)",
"new_top": "[]"
},
{
"rule_applied": "introduce_diveq ([(\\\"Minion\\\", 4200)])",
"initial_expression": "(2 = SafeDiv(8, a))",
"tranformed_expression": "DivEq(8, a, 2)",
"new_top": "[]"
},
{
"Number of rules applied": 5
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[
{
"rule_applied": "div_to_bubble ([(\\\"Bubble\\\", 6000)])",
"initial_expression": "UnsafeDiv(b, c)",
"tranformed_expression": "{SafeDiv(b, c) @ (c != 0)}",
"new_top": "[]"
},
{
"rule_applied": "bubble_up ([(\\\"Bubble\\\", 8900)])",
"initial_expression": "(a = {SafeDiv(b, c) @ (c != 0)})",
"tranformed_expression": "{(a = SafeDiv(b, c)) @ And([(c != 0)])}",
"new_top": "[]"
},
{
"rule_applied": "expand_bubble ([(\\\"Bubble\\\", 8900)])",
"initial_expression": "{(a = SafeDiv(b, c)) @ And([(c != 0)])}",
"tranformed_expression": "And([(a = SafeDiv(b, c)), And([(c != 0)])])",
"new_top": "[]"
},
{
"rule_applied": "remove_unit_vector_and ([(\\\"Base\\\", 8800)])",
"initial_expression": "And([(c != 0)])",
"tranformed_expression": "(c != 0)",
"new_top": "[]"
},
{
"rule_applied": "distribute_not_over_and ([(\\\"Base\\\", 8400)])",
"initial_expression": "Not(And([(a = SafeDiv(b, c)), (c != 0)]))",
"tranformed_expression": "Or([Not((a = SafeDiv(b, c))), Not((c != 0))])",
"new_top": "[]"
},
{
"rule_applied": "negated_eq_to_neq ([(\\\"Base\\\", 8800)])",
"initial_expression": "Not((a = SafeDiv(b, c)))",
"tranformed_expression": "(a != SafeDiv(b, c))",
"new_top": "[]"
},
{
"rule_applied": "negated_neq_to_eq ([(\\\"Base\\\", 8800)])",
"initial_expression": "Not((c != 0))",
"tranformed_expression": "(c = 0)",
"new_top": "[]"
},
{
"rule_applied": "flatten_binop ([(\\\"Minion\\\", 4400)])",
"initial_expression": "(a != SafeDiv(b, c))",
"tranformed_expression": "(a != __0)",
"new_top": "[__0 =aux SafeDiv(b, c)]"
},
{
"rule_applied": "introduce_diveq ([(\\\"Minion\\\", 4200)])",
"initial_expression": "__0 =aux SafeDiv(b, c)",
"tranformed_expression": "DivEq(b, c, __0)",
"new_top": "[]"
},
{
"Number of rules applied": 9
}
]
Loading