Ctrl K
ComunidadGuías…

tariff/wrapper_test.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package tariff

import (
	"context"
	"errors"
	"sync"
	"testing"
	"time"

	"github.com/evcc-io/evcc/api"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// retryTariff fails instantiation on demand
type retryTariff struct {
	mu    sync.Mutex
	err   error
	calls int
}

// created returns the number of creation attempts
func (t *retryTariff) created() int {
	t.mu.Lock()
	defer t.mu.Unlock()
	return t.calls
}

func (t *retryTariff) setErr(err error) {
	t.mu.Lock()
	defer t.mu.Unlock()
	t.err = err
}

func (t *retryTariff) Rates() (api.Rates, error) {
	t.mu.Lock()
	defer t.mu.Unlock()
	if t.err != nil {
		return nil, t.err
	}
	now := time.Now().Truncate(SlotDuration)
	return api.Rates{{Start: now, End: now.Add(SlotDuration), Value: 1}}, nil
}

func (t *retryTariff) Type() api.TariffType {
	return api.TariffTypePriceForecast
}

var retryable = new(retryTariff)

func init() {
	registry.AddCtx("test-retry", func(context.Context, map[string]any) (api.Tariff, error) {
		retryable.mu.Lock()
		retryable.calls++
		retryable.mu.Unlock()

		if _, err := retryable.Rates(); err != nil {
			return nil, err
		}
		return retryable, nil
	})
}

func TestWrapperRetry(t *testing.T) {
	retryable.setErr(errors.New("unavailable"))

	_, err := NewFromConfig(context.TODO(), "test-retry", nil)
	require.Error(t, err)

	res := NewWrapper(context.TODO(), "test-retry", nil, err)
	w := res.(*Wrapper)

	// creation has just failed: no immediate retry
	assert.False(t, w.retriedAt.IsZero())
	created := retryable.created()

	_, err = res.Rates()
	require.ErrorContains(t, err, "tariff not available")
	assert.Equal(t, api.TariffType(0), res.Type())
	assert.Equal(t, created, retryable.created())

	// tariff becomes available but retry interval not elapsed: still unavailable
	retryable.setErr(nil)
	_, err = res.Rates()
	require.Error(t, err)

	// retry interval elapsed: next call creates the tariff
	w.mu.Lock()
	w.retriedAt = time.Time{}
	w.mu.Unlock()

	rr, err := res.Rates()
	require.NoError(t, err)
	assert.Len(t, rr, 1)
	assert.Equal(t, api.TariffTypePriceForecast, res.Type())

	// tariff fails at runtime: error passed through, no re-creation
	retryable.setErr(api.ErrOutdated)
	_, err = res.Rates()
	require.ErrorIs(t, err, api.ErrOutdated)
	assert.Same(t, retryable, w.tariff)
}