evcc-io/core/energy_metrics_test.go

155 lines
3.1 KiB
Go

package core
import (
"testing"
)
func isEqualFloat64(a, b *float64) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
return *a == *b
}
func TestEnergyMetrics(t *testing.T) {
f := func(f float64) *float64 { return &f }
type tcStep = struct {
kWh, greenShare float64
effPrice, effCo2 *float64
}
tc := []struct {
title string
steps []tcStep
totalWh, solarPercentage float64
price, pricePerKWh, co2PerKWh *float64
}{
{
"initial state",
[]tcStep{},
0, 0, nil, nil, nil,
},
{
"energy value",
[]tcStep{
{0.1, 0, nil, nil},
{0.2, 0, nil, nil},
},
200, 0, nil, nil, nil,
},
{
"ignore lower energy value",
[]tcStep{
{0.2, 0, nil, nil},
{0.1, 0, nil, nil},
},
200, 0, nil, nil, nil,
},
{
"half solar",
[]tcStep{
{0.1, 1, nil, nil},
{0.2, 0, nil, nil},
},
200, 50, nil, nil, nil,
},
{
"only solar",
[]tcStep{
{0.1, 1, nil, nil},
{0.2, 1, nil, nil},
},
200, 100, nil, nil, nil,
},
{
"static price",
[]tcStep{
{1, 0, f(0.5), nil},
},
1000, 0, f(0.5), f(0.5), nil,
},
{
"dynamic price",
[]tcStep{
{1, 0, f(1), nil},
{2, 0, f(0), nil},
},
2000, 0, f(1), f(0.5), nil,
},
{
"dynamic price",
[]tcStep{
{2, 0, f(1), nil},
{4, 0, f(0), nil},
},
4000, 0, f(2), f(0.5), nil,
},
{
"static co2",
[]tcStep{
{1, 0, nil, f(500)},
},
1000, 0, nil, nil, f(500),
},
{
"dynamic co2",
[]tcStep{
{1, 0, nil, f(1000)},
{2, 0, nil, f(0)},
},
2000, 0, nil, nil, f(500),
},
{
"grid only, half, full solar, half, grid only",
[]tcStep{
{1, 0, f(2), f(200)},
{2, 0.5, f(1), f(50)},
{3, 1, f(0), f(0)},
{4, 0.5, f(1), f(50)},
{5, 0, f(2), f(200)},
},
5000, 40, f(6), f(1.2), f(100),
},
}
for _, tc := range tc {
var s EnergyMetrics
for _, tc := range tc.steps {
s.SetEnvironment(tc.greenShare, tc.effPrice, tc.effCo2)
s.Update(tc.kWh)
}
if s.TotalWh() != tc.totalWh {
t.Errorf("%s: TotalWh was incorrect, got: %.3f, want: %.3f.", tc.title, s.TotalWh(), tc.totalWh)
}
if s.SolarPercentage() != tc.solarPercentage {
t.Errorf("%s: SolarPercentage was incorrect, got: %.3f, want: %.3f.", tc.title, s.SolarPercentage(), tc.solarPercentage)
}
price := s.Price()
if !isEqualFloat64(price, tc.price) {
t.Errorf("%s: Price was incorrect, got: %v, want: %v.", tc.title, *price, *tc.price)
}
pricePerKWh := s.PricePerKWh()
if !isEqualFloat64(pricePerKWh, tc.pricePerKWh) {
t.Errorf("%s: PricePerKWh was incorrect, got: %v, want: %v.", tc.title, *pricePerKWh, *tc.pricePerKWh)
}
co2PerKWh := s.Co2PerKWh()
if !isEqualFloat64(co2PerKWh, tc.co2PerKWh) {
t.Errorf("%s: Co2PerKWh was incorrect, got: %v, want: %v.", tc.title, *co2PerKWh, *tc.co2PerKWh)
}
}
// reset
var s EnergyMetrics
s.SetEnvironment(1, f(1), f(1))
s.Update(1)
s.Reset()
if s.TotalWh() != 0 || s.SolarPercentage() != 0 || s.Co2PerKWh() != nil || s.Price() != nil || s.PricePerKWh() != nil {
t.Errorf("Metrics not properly reset %+v", s)
}
}