168 lines
3.8 KiB
Go
168 lines
3.8 KiB
Go
package tariff
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/benbjohnson/clock"
|
|
"github.com/evcc-io/evcc/api"
|
|
"github.com/evcc-io/evcc/tariff/fixed"
|
|
"github.com/jinzhu/now"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestFixed(t *testing.T) {
|
|
tf := &Fixed{
|
|
embed: &embed{},
|
|
clock: clock.NewMock(),
|
|
zones: []fixed.Zone{
|
|
{Price: 0.3},
|
|
},
|
|
}
|
|
|
|
var expect api.Rates
|
|
for dow := range 7 {
|
|
dayStart := now.With(tf.clock.Now()).BeginningOfDay().AddDate(0, 0, dow)
|
|
|
|
for hour := range 24 {
|
|
expect = append(expect, api.Rate{
|
|
Value: 0.3,
|
|
Start: dayStart.Add(time.Hour * time.Duration(hour)),
|
|
End: dayStart.Add(time.Hour * time.Duration(hour+1)),
|
|
})
|
|
}
|
|
}
|
|
|
|
rates, err := tf.Rates()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expect, rates)
|
|
}
|
|
|
|
func TestFixedSplitZones(t *testing.T) {
|
|
at, err := NewFixedFromConfig(map[string]any{
|
|
"price": 0.5,
|
|
"zones": []struct {
|
|
Price float64
|
|
Hours string
|
|
}{
|
|
{0.1, "0-5:30,20-21,21-0"},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
tf := at.(*Fixed)
|
|
tf.clock = clock.NewMock()
|
|
|
|
var expect api.Rates
|
|
for i := range 7 {
|
|
dayStart := now.With(tf.clock.Now()).BeginningOfDay().AddDate(0, 0, i)
|
|
|
|
// 00:00-05:00 0.1
|
|
for hour := range 5 {
|
|
expect = append(expect, api.Rate{
|
|
Value: 0.1,
|
|
Start: dayStart.Add(time.Hour * time.Duration(hour)),
|
|
End: dayStart.Add(time.Hour * time.Duration(hour+1)),
|
|
})
|
|
}
|
|
|
|
// 05:00-05:30 0.1
|
|
expect = append(expect, api.Rate{
|
|
Value: 0.1,
|
|
Start: dayStart.Add(5 * time.Hour),
|
|
End: dayStart.Add(5*time.Hour + 30*time.Minute),
|
|
})
|
|
|
|
// 05:30-06:00 0.5
|
|
expect = append(expect, api.Rate{
|
|
Value: 0.5,
|
|
Start: dayStart.Add(5*time.Hour + 30*time.Minute),
|
|
End: dayStart.Add(6 * time.Hour),
|
|
})
|
|
|
|
// 06:00-20:00 0.5
|
|
for hour := 6; hour < 20; hour++ {
|
|
expect = append(expect, api.Rate{
|
|
Value: 0.5,
|
|
Start: dayStart.Add(time.Hour * time.Duration(hour)),
|
|
End: dayStart.Add(time.Hour * time.Duration(hour+1)),
|
|
})
|
|
}
|
|
|
|
// 20:00-21:00,21:00-00:00 0.1
|
|
for hour := 20; hour < 24; hour++ {
|
|
expect = append(expect, api.Rate{
|
|
Value: 0.1,
|
|
Start: dayStart.Add(time.Hour * time.Duration(hour)),
|
|
End: dayStart.Add(time.Hour * time.Duration(hour+1)),
|
|
})
|
|
}
|
|
}
|
|
|
|
rates, err := tf.Rates()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expect, rates)
|
|
}
|
|
|
|
func TestFixedChargesZonesMarkers(t *testing.T) {
|
|
at, err := NewFixedFromConfig(map[string]any{
|
|
"price": 0.5,
|
|
"chargesZones": []struct {
|
|
Charges float64
|
|
Hours string
|
|
}{
|
|
{0.1, "0-5:30"},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
tf := at.(*Fixed)
|
|
tf.clock = clock.NewMock()
|
|
|
|
rates, err := tf.Rates()
|
|
require.NoError(t, err)
|
|
|
|
dayStart := now.With(tf.clock.Now()).BeginningOfDay()
|
|
|
|
// charges zone ends mid-hour at 05:30 - the price change must take effect there, not at 06:00
|
|
require.GreaterOrEqual(t, len(rates), 2)
|
|
assert.Equal(t, dayStart.Add(5*time.Hour), rates[5].Start)
|
|
assert.Equal(t, dayStart.Add(5*time.Hour+30*time.Minute), rates[5].End)
|
|
assert.Equal(t, 0.6, rates[5].Value)
|
|
assert.Equal(t, dayStart.Add(5*time.Hour+30*time.Minute), rates[6].Start)
|
|
assert.Equal(t, 0.5, rates[6].Value)
|
|
}
|
|
|
|
func TestFixedChargesZonesOrder(t *testing.T) {
|
|
at, err := NewFixedFromConfig(map[string]any{
|
|
"price": 0.5,
|
|
"zones": []struct {
|
|
Price float64
|
|
Hours string
|
|
}{
|
|
{0.2, "12-14"},
|
|
},
|
|
"chargesZones": []struct {
|
|
Charges float64
|
|
Hours string
|
|
}{
|
|
{0.1, "0-5:30"},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
tf := at.(*Fixed)
|
|
tf.clock = clock.NewMock()
|
|
|
|
rates, err := tf.Rates()
|
|
require.NoError(t, err)
|
|
|
|
// rates must stay ordered and contiguous even if charges zone markers don't align with price zones
|
|
for i, r := range rates {
|
|
require.True(t, r.End.After(r.Start), "invalid rate %d: %v", i, r)
|
|
if i > 0 {
|
|
require.Equal(t, rates[i-1].End, r.Start, "non-contiguous rate %d: %v", i, r)
|
|
}
|
|
}
|
|
}
|