package playback import ( "context" "errors" "testing" "time" "github.com/google/uuid" "github.com/stretchr/testify/require" "pipu/api/internal/api/gen" "pipu/api/internal/auth" "pipu/api/internal/library" "pipu/api/internal/platform/sign" ) type reactionReaderFunc func(context.Context, uuid.UUID, []uuid.UUID) (map[uuid.UUID]string, error) func (f reactionReaderFunc) Reactions(ctx context.Context, user uuid.UUID, ids []uuid.UUID) (map[uuid.UUID]string, error) { return f(ctx, user, ids) } func TestPersonalizerBatch(t *testing.T) { user, first, second := uuid.New(), uuid.New(), uuid.New() calls := 0 reader := reactionReaderFunc(func(_ context.Context, got uuid.UUID, ids []uuid.UUID) (map[uuid.UUID]string, error) { calls++ require.Equal(t, user, got) require.Equal(t, []uuid.UUID{first, second}, ids) return map[uuid.UUID]string{second: "dislike"}, nil }) signer, err := sign.New("") require.NoError(t, err) p := NewPersonalizer(reader, signer) now := time.Now().UTC() p.now = func() time.Time { return now } rows := []library.TrackRow{{ID: first}, {ID: second}} out := []gen.Track{{Available: true}, {Available: false}} require.NoError(t, p.Personalize(context.Background(), rows, out)) require.Zero(t, calls, "anonymous catalog does not query personal data") ctx := auth.WithPrincipal(context.Background(), auth.Principal{UserID: user}) require.NoError(t, p.Personalize(ctx, rows, out)) require.Equal(t, 1, calls, "one reaction query for the entire batch") require.Equal(t, StreamURL(signer, user, first, now), *out[0].StreamUrl) require.Nil(t, out[1].StreamUrl, "unavailable tracks must not receive stream links") require.Equal(t, gen.Reaction("dislike"), *out[1].Reaction) } func TestPersonalizerReadFailure(t *testing.T) { failure := errors.New("database unavailable") p := NewPersonalizer(reactionReaderFunc(func(context.Context, uuid.UUID, []uuid.UUID) (map[uuid.UUID]string, error) { return nil, failure }), nil) ctx := auth.WithPrincipal(context.Background(), auth.Principal{UserID: uuid.New()}) require.ErrorIs(t, p.Personalize(ctx, nil, nil), failure) }