@@ -167,3 +167,316 @@ pub struct ProcessParameter {
167167 /// PJ energy output in a year.
168168 pub capacity_to_activity : f64 ,
169169}
170+
171+ #[ cfg( test) ]
172+ mod tests {
173+ use super :: * ;
174+ use crate :: commodity:: {
175+ BalanceType , CommodityLevy , CommodityLevyMap , CommodityType , DemandMap ,
176+ } ;
177+ use crate :: fixture:: { region_id, time_slice} ;
178+ use crate :: time_slice:: TimeSliceLevel ;
179+ use rstest:: { fixture, rstest} ;
180+ use std:: rc:: Rc ;
181+
182+ #[ fixture]
183+ fn commodity_with_levy ( region_id : RegionID , time_slice : TimeSliceID ) -> Rc < Commodity > {
184+ let mut levies = CommodityLevyMap :: new ( ) ;
185+ // Add levy for the default region and time slice
186+ levies. insert (
187+ ( region_id. clone ( ) , 2020 , time_slice. clone ( ) ) ,
188+ CommodityLevy {
189+ balance_type : BalanceType :: Net ,
190+ value : 10.0 ,
191+ } ,
192+ ) ;
193+ // Add levy for a different region
194+ levies. insert (
195+ ( "USA" . into ( ) , 2020 , time_slice. clone ( ) ) ,
196+ CommodityLevy {
197+ balance_type : BalanceType :: Net ,
198+ value : 5.0 ,
199+ } ,
200+ ) ;
201+ // Add levy for a different year
202+ levies. insert (
203+ ( region_id. clone ( ) , 2030 , time_slice. clone ( ) ) ,
204+ CommodityLevy {
205+ balance_type : BalanceType :: Net ,
206+ value : 7.0 ,
207+ } ,
208+ ) ;
209+ // Add levy for a different time slice
210+ levies. insert (
211+ (
212+ region_id. clone ( ) ,
213+ 2020 ,
214+ TimeSliceID {
215+ season : "summer" . into ( ) ,
216+ time_of_day : "day" . into ( ) ,
217+ } ,
218+ ) ,
219+ CommodityLevy {
220+ balance_type : BalanceType :: Net ,
221+ value : 3.0 ,
222+ } ,
223+ ) ;
224+
225+ Rc :: new ( Commodity {
226+ id : "test_commodity" . into ( ) ,
227+ description : "Test commodity" . into ( ) ,
228+ kind : CommodityType :: ServiceDemand ,
229+ time_slice_level : TimeSliceLevel :: Annual ,
230+ levies,
231+ demand : DemandMap :: new ( ) ,
232+ } )
233+ }
234+
235+ #[ fixture]
236+ fn commodity_with_consumption_levy (
237+ region_id : RegionID ,
238+ time_slice : TimeSliceID ,
239+ ) -> Rc < Commodity > {
240+ let mut levies = CommodityLevyMap :: new ( ) ;
241+ levies. insert (
242+ ( region_id, 2020 , time_slice) ,
243+ CommodityLevy {
244+ balance_type : BalanceType :: Consumption ,
245+ value : 10.0 ,
246+ } ,
247+ ) ;
248+
249+ Rc :: new ( Commodity {
250+ id : "test_commodity" . into ( ) ,
251+ description : "Test commodity" . into ( ) ,
252+ kind : CommodityType :: ServiceDemand ,
253+ time_slice_level : TimeSliceLevel :: Annual ,
254+ levies,
255+ demand : DemandMap :: new ( ) ,
256+ } )
257+ }
258+
259+ #[ fixture]
260+ fn commodity_with_production_levy (
261+ region_id : RegionID ,
262+ time_slice : TimeSliceID ,
263+ ) -> Rc < Commodity > {
264+ let mut levies = CommodityLevyMap :: new ( ) ;
265+ levies. insert (
266+ ( region_id, 2020 , time_slice) ,
267+ CommodityLevy {
268+ balance_type : BalanceType :: Production ,
269+ value : 10.0 ,
270+ } ,
271+ ) ;
272+
273+ Rc :: new ( Commodity {
274+ id : "test_commodity" . into ( ) ,
275+ description : "Test commodity" . into ( ) ,
276+ kind : CommodityType :: ServiceDemand ,
277+ time_slice_level : TimeSliceLevel :: Annual ,
278+ levies,
279+ demand : DemandMap :: new ( ) ,
280+ } )
281+ }
282+
283+ #[ fixture]
284+ fn commodity_with_incentive ( region_id : RegionID , time_slice : TimeSliceID ) -> Rc < Commodity > {
285+ let mut levies = CommodityLevyMap :: new ( ) ;
286+ levies. insert (
287+ ( region_id, 2020 , time_slice) ,
288+ CommodityLevy {
289+ balance_type : BalanceType :: Net ,
290+ value : -5.0 ,
291+ } ,
292+ ) ;
293+
294+ Rc :: new ( Commodity {
295+ id : "test_commodity" . into ( ) ,
296+ description : "Test commodity" . into ( ) ,
297+ kind : CommodityType :: ServiceDemand ,
298+ time_slice_level : TimeSliceLevel :: Annual ,
299+ levies,
300+ demand : DemandMap :: new ( ) ,
301+ } )
302+ }
303+
304+ #[ fixture]
305+ fn commodity_no_levies ( ) -> Rc < Commodity > {
306+ Rc :: new ( Commodity {
307+ id : "test_commodity" . into ( ) ,
308+ description : "Test commodity" . into ( ) ,
309+ kind : CommodityType :: ServiceDemand ,
310+ time_slice_level : TimeSliceLevel :: Annual ,
311+ levies : CommodityLevyMap :: new ( ) ,
312+ demand : DemandMap :: new ( ) ,
313+ } )
314+ }
315+
316+ #[ rstest]
317+ fn test_get_levy_no_levies (
318+ commodity_no_levies : Rc < Commodity > ,
319+ region_id : RegionID ,
320+ time_slice : TimeSliceID ,
321+ ) {
322+ let flow = ProcessFlow {
323+ commodity : commodity_no_levies,
324+ coeff : 1.0 ,
325+ kind : FlowType :: Fixed ,
326+ cost : 0.0 ,
327+ is_pac : true ,
328+ } ;
329+
330+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & time_slice) , 0.0 ) ;
331+ }
332+
333+ #[ rstest]
334+ fn test_get_levy_with_levy (
335+ commodity_with_levy : Rc < Commodity > ,
336+ region_id : RegionID ,
337+ time_slice : TimeSliceID ,
338+ ) {
339+ let flow = ProcessFlow {
340+ commodity : commodity_with_levy,
341+ coeff : 1.0 ,
342+ kind : FlowType :: Fixed ,
343+ cost : 0.0 ,
344+ is_pac : true ,
345+ } ;
346+
347+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & time_slice) , 10.0 ) ;
348+ }
349+
350+ #[ rstest]
351+ fn test_get_levy_with_incentive (
352+ commodity_with_incentive : Rc < Commodity > ,
353+ region_id : RegionID ,
354+ time_slice : TimeSliceID ,
355+ ) {
356+ let flow = ProcessFlow {
357+ commodity : commodity_with_incentive,
358+ coeff : 1.0 ,
359+ kind : FlowType :: Fixed ,
360+ cost : 0.0 ,
361+ is_pac : true ,
362+ } ;
363+
364+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & time_slice) , -5.0 ) ;
365+ }
366+
367+ #[ rstest]
368+ fn test_get_levy_different_region ( commodity_with_levy : Rc < Commodity > , time_slice : TimeSliceID ) {
369+ let flow = ProcessFlow {
370+ commodity : commodity_with_levy,
371+ coeff : 1.0 ,
372+ kind : FlowType :: Fixed ,
373+ cost : 0.0 ,
374+ is_pac : true ,
375+ } ;
376+
377+ assert_eq ! ( flow. get_levy( & "USA" . into( ) , 2020 , & time_slice) , 5.0 ) ;
378+ }
379+
380+ #[ rstest]
381+ fn test_get_levy_different_year (
382+ commodity_with_levy : Rc < Commodity > ,
383+ region_id : RegionID ,
384+ time_slice : TimeSliceID ,
385+ ) {
386+ let flow = ProcessFlow {
387+ commodity : commodity_with_levy,
388+ coeff : 1.0 ,
389+ kind : FlowType :: Fixed ,
390+ cost : 0.0 ,
391+ is_pac : true ,
392+ } ;
393+
394+ assert_eq ! ( flow. get_levy( & region_id, 2030 , & time_slice) , 7.0 ) ;
395+ }
396+
397+ #[ rstest]
398+ fn test_get_levy_different_time_slice ( commodity_with_levy : Rc < Commodity > , region_id : RegionID ) {
399+ let flow = ProcessFlow {
400+ commodity : commodity_with_levy,
401+ coeff : 1.0 ,
402+ kind : FlowType :: Fixed ,
403+ cost : 0.0 ,
404+ is_pac : true ,
405+ } ;
406+
407+ let different_time_slice = TimeSliceID {
408+ season : "summer" . into ( ) ,
409+ time_of_day : "day" . into ( ) ,
410+ } ;
411+
412+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & different_time_slice) , 3.0 ) ;
413+ }
414+
415+ #[ rstest]
416+ fn test_get_levy_consumption_positive_coeff (
417+ commodity_with_consumption_levy : Rc < Commodity > ,
418+ region_id : RegionID ,
419+ time_slice : TimeSliceID ,
420+ ) {
421+ let flow = ProcessFlow {
422+ commodity : commodity_with_consumption_levy,
423+ coeff : 1.0 , // Positive coefficient means production
424+ kind : FlowType :: Fixed ,
425+ cost : 0.0 ,
426+ is_pac : true ,
427+ } ;
428+
429+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & time_slice) , 0.0 ) ;
430+ }
431+
432+ #[ rstest]
433+ fn test_get_levy_consumption_negative_coeff (
434+ commodity_with_consumption_levy : Rc < Commodity > ,
435+ region_id : RegionID ,
436+ time_slice : TimeSliceID ,
437+ ) {
438+ let flow = ProcessFlow {
439+ commodity : commodity_with_consumption_levy,
440+ coeff : -1.0 , // Negative coefficient means consumption
441+ kind : FlowType :: Fixed ,
442+ cost : 0.0 ,
443+ is_pac : true ,
444+ } ;
445+
446+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & time_slice) , 10.0 ) ;
447+ }
448+
449+ #[ rstest]
450+ fn test_get_levy_production_positive_coeff (
451+ commodity_with_production_levy : Rc < Commodity > ,
452+ region_id : RegionID ,
453+ time_slice : TimeSliceID ,
454+ ) {
455+ let flow = ProcessFlow {
456+ commodity : commodity_with_production_levy,
457+ coeff : 1.0 , // Positive coefficient means production
458+ kind : FlowType :: Fixed ,
459+ cost : 0.0 ,
460+ is_pac : true ,
461+ } ;
462+
463+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & time_slice) , 10.0 ) ;
464+ }
465+
466+ #[ rstest]
467+ fn test_get_levy_production_negative_coeff (
468+ commodity_with_production_levy : Rc < Commodity > ,
469+ region_id : RegionID ,
470+ time_slice : TimeSliceID ,
471+ ) {
472+ let flow = ProcessFlow {
473+ commodity : commodity_with_production_levy,
474+ coeff : -1.0 , // Negative coefficient means consumption
475+ kind : FlowType :: Fixed ,
476+ cost : 0.0 ,
477+ is_pac : true ,
478+ } ;
479+
480+ assert_eq ! ( flow. get_levy( & region_id, 2020 , & time_slice) , 0.0 ) ;
481+ }
482+ }
0 commit comments