Files
pipu-music/services/api/internal/playback/rules_test.go
T
mrleo1nidandClaude Opus 5.5 c05e523cbe
ci / api / api (push) Successful in 29s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 35s
ci / ts / ts (packages + web) (push) Failing after 49s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m1s
feat(api): streaming, transcoding, events, history and likes (M3)
- tracks carry a stream_url signed for the user for 12 h and the
  user's reaction; /stream checks the signature, expiry and that the
  user is not blocked, then hands the file to nginx by X-Accel-Redirect
  (or serves it with Range support when X_ACCEL=false)
- original by default; formats browsers can't play and explicit
  high/medium/low go through Opus transcoding, never upwards: a lossy
  source under the target bitrate stays original; transcodes are
  cached per file and size, deduplicated in flight, limited by
  TRANSCODE_CONCURRENCY and trimmed hourly by LRU to the size limit
- /events takes up to 500 events with client UUIDs, drops repeats and
  events older than 30 days, counts plays (≥ half or 4 min, or
  finished), early skips and history entries (≥ 30 s)
- history with clearing, likes and dislikes with cursors and totals,
  track reactions, playback state with last-write-wins, tracks batch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 07:25:15 +03:00

49 lines
1.6 KiB
Go

package playback
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTarget(t *testing.T) {
cases := []struct {
q, format, codec string
bitrate int
want string
}{
{"auto", "flac", "flac", 900000, ""},
{"original", "mp3", "mp3", 320000, ""},
{"auto", "ape", "ape", 800000, "high"},
{"original", "aiff", "pcm_s16be", 1411000, "high"},
{"high", "flac", "flac", 900000, "high"},
{"high", "mp3", "mp3", 192000, ""}, // ниже целевых 256 — оригинал
{"medium", "mp3", "mp3", 320000, "medium"},
{"low", "opus", "opus", 64000, ""},
{"medium", "m4a", "aac", 0, "medium"}, // битрейт неизвестен — транскодируем
}
for _, tc := range cases {
assert.Equal(t, tc.want, Target(tc.q, tc.format, tc.codec, tc.bitrate), "%+v", tc)
}
}
func TestJudge(t *testing.T) {
const min4 = 4 * 60 * 1000
o := Judge("play_end", 200000, 210000)
assert.Equal(t, Outcome{Counted: true, Complete: true, History: true, PlayedMs: 200000}, o)
o = Judge("skip", 10000, 210000)
assert.True(t, o.Skip)
assert.True(t, o.EarlySkip)
assert.False(t, o.Counted)
assert.False(t, o.History)
assert.True(t, Judge("skip", 105000, 210000).Counted, "half of the track")
assert.False(t, Judge("skip", 104000, 210000).Counted)
assert.True(t, Judge("skip", min4, 20*60*1000).Counted, "4 minutes of a long track")
assert.True(t, Judge("skip", 31000, 210000).History)
assert.True(t, Judge("play_end", 20000, 20000).History, "short track played to the end")
assert.False(t, Judge("skip", 15000, 20000).History)
assert.Equal(t, Outcome{}, Judge("pause", 1000, 1000))
}