Skip to content

Commit 4b130da

Browse files
authored
Merge pull request #1056 from EnergySystemsModellingLab/add-more-tests
Add helpers for patching code and use in some new tests
2 parents 696767e + 10a9763 commit 4b130da

File tree

4 files changed

+143
-8
lines changed

4 files changed

+143
-8
lines changed

src/asset.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,9 +1295,11 @@ mod tests {
12951295
use super::*;
12961296
use crate::commodity::Commodity;
12971297
use crate::fixture::{
1298-
assert_error, asset, process, process_activity_limits_map, process_flows_map,
1299-
process_parameter_map, region_id, svd_commodity, time_slice, time_slice_info,
1298+
assert_error, assert_patched_runs_ok_simple, assert_validate_fails_with_simple, asset,
1299+
process, process_activity_limits_map, process_flows_map, process_parameter_map, region_id,
1300+
svd_commodity, time_slice, time_slice_info,
13001301
};
1302+
use crate::patch::FilePatch;
13011303
use crate::process::{FlowType, Process, ProcessFlow, ProcessParameter};
13021304
use crate::region::RegionID;
13031305
use crate::time_slice::{TimeSliceID, TimeSliceInfo};
@@ -2018,4 +2020,53 @@ mod tests {
20182020
Asset::new_candidate(process.into(), "GBR".into(), Capacity(1.0), 2020).unwrap();
20192021
asset.decommission(2025, "");
20202022
}
2023+
2024+
#[test]
2025+
fn commission_year_before_time_horizon() {
2026+
let processes_patch = FilePatch::new("processes.csv")
2027+
.with_deletion("GASDRV,Dry gas extraction,all,GASPRD,2020,2040,1.0")
2028+
.with_addition("GASDRV,Dry gas extraction,all,GASPRD,1980,2040,1.0");
2029+
2030+
// Check we can run model with asset commissioned before time horizon (simple starts in
2031+
// 2020)
2032+
let patches = vec![
2033+
processes_patch.clone(),
2034+
FilePatch::new("assets.csv").with_addition("GASDRV,GBR,A0_GEX,4002.26,1980"),
2035+
];
2036+
assert_patched_runs_ok_simple!(patches);
2037+
2038+
// This should fail if it is not one of the years supported by the process, though
2039+
let patches = vec![
2040+
processes_patch,
2041+
FilePatch::new("assets.csv").with_addition("GASDRV,GBR,A0_GEX,4002.26,1970"),
2042+
];
2043+
assert_validate_fails_with_simple!(
2044+
patches,
2045+
"Agent A0_GEX has asset with commission year 1970, not within process GASDRV commission years: 1980..=2040"
2046+
);
2047+
}
2048+
2049+
#[test]
2050+
fn commission_year_after_time_horizon() {
2051+
let processes_patch = FilePatch::new("processes.csv")
2052+
.with_deletion("GASDRV,Dry gas extraction,all,GASPRD,2020,2040,1.0")
2053+
.with_addition("GASDRV,Dry gas extraction,all,GASPRD,2020,2050,1.0");
2054+
2055+
// Check we can run model with asset commissioned after time horizon (simple ends in 2040)
2056+
let patches = vec![
2057+
processes_patch.clone(),
2058+
FilePatch::new("assets.csv").with_addition("GASDRV,GBR,A0_GEX,4002.26,2050"),
2059+
];
2060+
assert_patched_runs_ok_simple!(patches);
2061+
2062+
// This should fail if it is not one of the years supported by the process, though
2063+
let patches = vec![
2064+
processes_patch,
2065+
FilePatch::new("assets.csv").with_addition("GASDRV,GBR,A0_GEX,4002.26,2060"),
2066+
];
2067+
assert_validate_fails_with_simple!(
2068+
patches,
2069+
"Agent A0_GEX has asset with commission year 2060, not within process GASDRV commission years: 2020..=2050"
2070+
);
2071+
}
20212072
}

src/fixture.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,32 @@ macro_rules! patch_and_validate_simple {
6262
})()
6363
}};
6464
}
65-
// Currently unused outside this file
66-
// pub(crate) use patch_and_validate_simple;
65+
pub(crate) use patch_and_validate_simple;
66+
67+
/// Check whether validation succeeds for simple example with patches
68+
macro_rules! assert_validate_ok_simple {
69+
($file_patches:expr) => {
70+
assert!(crate::fixture::patch_and_validate_simple!($file_patches).is_ok())
71+
};
72+
}
73+
pub(crate) use assert_validate_ok_simple;
74+
75+
/// Check whether validation fails with specific message
76+
macro_rules! assert_validate_fails_with_simple {
77+
($file_patches:expr, $expected_msg:expr) => {
78+
let result = crate::fixture::patch_and_validate_simple!($file_patches);
79+
let msg = result
80+
.unwrap_err()
81+
.chain()
82+
.skip(1)
83+
.next()
84+
.unwrap()
85+
.to_string();
86+
87+
assert_eq!(msg, $expected_msg);
88+
};
89+
}
90+
pub(crate) use assert_validate_fails_with_simple;
6791

6892
/// Check whether the simple example runs successfully after applying file patches
6993
macro_rules! patch_and_run_simple {
@@ -79,8 +103,15 @@ macro_rules! patch_and_run_simple {
79103
})()
80104
}};
81105
}
82-
// Currently unused outside this file
83-
// pub(crate) use patch_and_run_simple;
106+
pub(crate) use patch_and_run_simple;
107+
108+
/// Check whether the simple example runs successfully after applying file patches
109+
macro_rules! assert_patched_runs_ok_simple {
110+
($file_patches:expr) => {
111+
assert!(crate::fixture::patch_and_run_simple!($file_patches).is_ok())
112+
};
113+
}
114+
pub(crate) use assert_patched_runs_ok_simple;
84115

85116
#[fixture]
86117
pub fn region_id() -> RegionID {

src/input/process/flow.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,11 @@ fn validate_secondary_flows(
338338
mod tests {
339339
use super::*;
340340
use crate::commodity::Commodity;
341-
use crate::fixture::{assert_error, process, sed_commodity, svd_commodity};
341+
use crate::fixture::{
342+
assert_error, assert_validate_fails_with_simple, assert_validate_ok_simple, process,
343+
sed_commodity, svd_commodity,
344+
};
345+
use crate::patch::FilePatch;
342346
use crate::process::{FlowType, Process, ProcessFlow, ProcessMap};
343347
use crate::units::{FlowPerActivity, MoneyPerFlow};
344348
use indexmap::IndexMap;
@@ -518,4 +522,53 @@ mod tests {
518522
validate_flows_and_update_primary_output(&mut processes, &flows_map, &milestone_years)
519523
.unwrap();
520524
}
525+
526+
#[test]
527+
fn flows_different_direction_different_years() {
528+
let patch = FilePatch::new("process_flows.csv")
529+
.with_deletion("GASPRC,GASPRD,all,all,-1.05,fixed,")
530+
.with_addition("GASPRC,GASPRD,all,2020;2030,-1.05,fixed,")
531+
.with_addition("GASPRC,GASPRD,all,2040,1.05,fixed,");
532+
assert_validate_fails_with_simple!(
533+
vec![patch],
534+
"Flow of commodity GASPRD in region GBR for process GASPRC behaves as input or output in different years."
535+
);
536+
}
537+
538+
#[test]
539+
fn missing_flow() {
540+
let patch = FilePatch::new("process_flows.csv")
541+
.with_deletion("GASPRC,GASPRD,all,all,-1.05,fixed,")
542+
.with_addition("GASPRC,GASPRD,all,2020;2030,-1.05,fixed,");
543+
assert_validate_fails_with_simple!(
544+
vec![patch],
545+
"Flow of commodity GASPRD in region GBR for process GASPRC does not cover all milestone years within the process range of activity."
546+
);
547+
}
548+
549+
#[test]
550+
fn coeff_zero() {
551+
let patch = FilePatch::new("process_flows.csv")
552+
.with_deletion("GASPRC,GASPRD,all,all,-1.05,fixed,")
553+
.with_addition("GASPRC,GASPRD,all,2020;2030,-1.05,fixed,")
554+
.with_addition("GASPRC,GASPRD,all,2040,0,fixed,");
555+
assert_validate_ok_simple!(vec![patch]);
556+
}
557+
558+
#[test]
559+
fn flows_not_needed_before_time_horizon() {
560+
// NB: Time horizon starts at 2020 for simple example
561+
//
562+
// Flows are only needed for milestone years. Check that users can omit them for
563+
// non-milestone years.
564+
let patches = vec![
565+
FilePatch::new("processes.csv")
566+
.with_deletion("GASDRV,Dry gas extraction,all,GASPRD,2020,2040,1.0")
567+
.with_addition("GASDRV,Dry gas extraction,all,GASPRD,1980,2040,1.0"),
568+
FilePatch::new("process_flows.csv")
569+
.with_deletion("GASPRC,GASPRD,all,all,-1.05,fixed,")
570+
.with_addition("GASPRC,GASPRD,all,2020;2030;2040,-1.05,fixed,"),
571+
];
572+
assert_validate_ok_simple!(patches);
573+
}
521574
}

src/patch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl ModelPatch {
110110
}
111111

112112
/// Structure to hold patches for a model csv file.
113-
#[derive(Debug)]
113+
#[derive(Debug, Clone)]
114114
pub struct FilePatch {
115115
/// The file that this patch applies to (e.g. "agents.csv")
116116
filename: String,

0 commit comments

Comments
 (0)