use super::*;
use crate::error::PanicOrBug;
use test_case::test_case;
struct GasChargeInput {
cgas: u64,
ggas: u64,
dependent_factor: u64,
}
#[derive(Debug, PartialEq, Eq)]
struct GasChargeOutput {
cgas: u64,
ggas: u64,
}
#[test_case(GasChargeInput{cgas: 0, ggas: 0, dependent_factor: 0} => Ok(GasChargeOutput{ cgas: 0, ggas: 0}); "zero")]
#[test_case(GasChargeInput{cgas: 0, ggas: 0, dependent_factor: 1} => Err(PanicOrBug::Panic(PanicReason::OutOfGas)); "no gas")]
#[test_case(GasChargeInput{cgas: 0, ggas: 2, dependent_factor: 1} => Err(PanicOrBug::Panic(PanicReason::OutOfGas)); "no call gas")]
#[test_case(GasChargeInput{cgas: 1, ggas: 1, dependent_factor: 1} => Ok(GasChargeOutput{ cgas: 0, ggas: 0}); "just enough")]
#[test_case(GasChargeInput{cgas: 10, ggas: 15, dependent_factor: 1} => Ok(GasChargeOutput{ cgas: 9, ggas: 14}); "heaps")]
fn test_gas_charge(input: GasChargeInput) -> SimpleResult<GasChargeOutput> {
let GasChargeInput {
mut cgas,
mut ggas,
dependent_factor,
} = input;
let mut cgas = RegMut::new(&mut cgas);
let mut ggas = RegMut::new(&mut ggas);
gas_charge(cgas.as_mut(), ggas.as_mut(), dependent_factor).map(|_| GasChargeOutput {
cgas: *cgas,
ggas: *ggas,
})
}
#[test]
fn test_gas_charges_ggas_on_out_of_gas() {
let mut cgas = 10;
let mut ggas = 15;
let gas = 20;
let mut cgas = RegMut::new(&mut cgas);
let mut ggas = RegMut::new(&mut ggas);
let _ = gas_charge(cgas.as_mut(), ggas.as_mut(), gas)
.expect_err("Gas charge should fail");
assert_eq!(*ggas, 5);
assert_eq!(*cgas, 0);
}
struct DepGasChargeInput {
input: GasChargeInput,
gas_cost: DependentCost,
}
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 0, ggas: 0, dependent_factor: 0},
gas_cost: DependentCost::from_units_per_gas(0, 1)
} => Ok(GasChargeOutput{ cgas: 0, ggas: 0}); "zero"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 1, ggas: 1, dependent_factor: 0},
gas_cost: DependentCost::from_units_per_gas(1, 1)
} => Ok(GasChargeOutput{ cgas: 0, ggas: 0}); "just base"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 1, ggas: 1, dependent_factor: 1},
gas_cost: DependentCost::from_units_per_gas(1, 2)
} => Ok(GasChargeOutput{ cgas: 0, ggas: 0}); "just base with gas"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 3, ggas: 3, dependent_factor: 8},
gas_cost: DependentCost::from_units_per_gas(1, 4)
} => Ok(GasChargeOutput{ cgas: 0, ggas: 0}); "base with gas and a unit"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 3, ggas: 3, dependent_factor: 5},
gas_cost: DependentCost::from_units_per_gas(0, 4)
} => Ok(GasChargeOutput{ cgas: 2, ggas: 2}); "base with gas and a unit and left over"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 0, ggas: 1, dependent_factor: 0},
gas_cost: DependentCost::from_units_per_gas(1, 1)
} => Err(PanicOrBug::Panic(PanicReason::OutOfGas)); "just base with no cgas"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 5, ggas: 10, dependent_factor: 25},
gas_cost: DependentCost::from_units_per_gas(1, 5)
} => Err(PanicOrBug::Panic(PanicReason::OutOfGas)); "unit with not enough cgas"
)]
fn test_dependent_gas_charge(input: DepGasChargeInput) -> SimpleResult<GasChargeOutput> {
let DepGasChargeInput { input, gas_cost } = input;
let GasChargeInput {
mut cgas,
mut ggas,
dependent_factor,
} = input;
let mut cgas = RegMut::new(&mut cgas);
let mut ggas = RegMut::new(&mut ggas);
dependent_gas_charge(cgas.as_mut(), ggas.as_mut(), gas_cost, dependent_factor).map(
|_| GasChargeOutput {
cgas: *cgas,
ggas: *ggas,
},
)
}
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 0, ggas: 0, dependent_factor: 0},
gas_cost: DependentCost::from_units_per_gas(0, 1)
} => Ok(GasChargeOutput{ cgas: 0, ggas: 0}); "zero"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 1, ggas: 1, dependent_factor: 0},
gas_cost: DependentCost::from_units_per_gas(1, 1)
} => Ok(GasChargeOutput{ cgas: 1, ggas: 1}); "even without base"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 1, ggas: 1, dependent_factor: 1},
gas_cost: DependentCost::from_units_per_gas(1, 2)
} => Ok(GasChargeOutput{ cgas: 1, ggas: 1}); "just base with gas"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 3, ggas: 3, dependent_factor: 8},
gas_cost: DependentCost::from_units_per_gas(1, 4)
} => Ok(GasChargeOutput{ cgas: 1, ggas: 1}); "base with gas and a unit"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 3, ggas: 3, dependent_factor: 5},
gas_cost: DependentCost::from_units_per_gas(0, 4)
} => Ok(GasChargeOutput{ cgas: 2, ggas: 2}); "base with gas and a unit and left over"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 0, ggas: 1, dependent_factor: 0},
gas_cost: DependentCost::from_units_per_gas(1, 1)
} => Ok(GasChargeOutput{ cgas: 0, ggas: 1}); "just base with no cgas"
)]
#[test_case(
DepGasChargeInput{
input: GasChargeInput{cgas: 5, ggas: 10, dependent_factor: 25},
gas_cost: DependentCost::from_units_per_gas(1, 4)
} => Err(PanicOrBug::Panic(PanicReason::OutOfGas)); "unit with not enough cgas"
)]
fn test_dependent_gas_charge_wihtout_base(
input: DepGasChargeInput,
) -> SimpleResult<GasChargeOutput> {
let DepGasChargeInput { input, gas_cost } = input;
let GasChargeInput {
mut cgas,
mut ggas,
dependent_factor,
} = input;
let mut cgas = RegMut::new(&mut cgas);
let mut ggas = RegMut::new(&mut ggas);
dependent_gas_charge_without_base(
cgas.as_mut(),
ggas.as_mut(),
gas_cost,
dependent_factor,
)
.map(|_| GasChargeOutput {
cgas: *cgas,
ggas: *ggas,
})
}
#[test]
#[should_panic]
fn vm_panics_on_cgas_gt_ggas() {
let dependent_factor = 25;
let gas_cost = DependentCost::from_units_per_gas(1, 5);
let mut cgas_val = 10;
let mut ggas_val = 5;
let mut cgas = RegMut::new(&mut cgas_val);
let mut ggas = RegMut::new(&mut ggas_val);
let _ =
dependent_gas_charge(cgas.as_mut(), ggas.as_mut(), gas_cost, dependent_factor);
}