2026-06-18 22:41:52 +08:00

149 lines
5.3 KiB
Go

package cprelation
import (
"errors"
"strings"
"testing"
)
func TestNormalizeRelationsForcesCPMaxCountAndKeepsSiblingLimits(t *testing.T) {
relations, err := normalizeRelations([]relationDTO{
relationInput(relationTypeCP, 99),
relationInput(relationTypeBrother, 7),
relationInput(relationTypeSister, 8),
})
if err != nil {
t.Fatalf("normalizeRelations() error = %v", err)
}
got := map[string]int32{}
for _, relation := range relations {
got[relation.RelationType] = relation.MaxCountPerUser
}
if got[relationTypeCP] != 1 {
t.Fatalf("CP max count = %d, want 1", got[relationTypeCP])
}
if got[relationTypeBrother] != 7 {
t.Fatalf("brother max count = %d, want 7", got[relationTypeBrother])
}
if got[relationTypeSister] != 8 {
t.Fatalf("sister max count = %d, want 8", got[relationTypeSister])
}
}
func TestNormalizeRelationsRequiresIncreasingLevelThresholds(t *testing.T) {
input := relationInput(relationTypeBrother, 5)
input.Levels[2].IntimacyThreshold = input.Levels[1].IntimacyThreshold
_, err := normalizeRelations([]relationDTO{
relationInput(relationTypeCP, 1),
input,
relationInput(relationTypeSister, 5),
})
if !errors.Is(err, ErrInvalidArgument) {
t.Fatalf("normalizeRelations() error = %v, want ErrInvalidArgument", err)
}
}
func TestNormalizeCPListOptionsBoundsPageSize(t *testing.T) {
options := normalizeCPListOptions(cpListOptions{Page: -3, PageSize: 1000, Status: "ALL", RelationType: " Brother "})
if options.Page != 1 {
t.Fatalf("page = %d, want 1", options.Page)
}
if options.PageSize != cpListMaxPageSize {
t.Fatalf("page size = %d, want max %d", options.PageSize, cpListMaxPageSize)
}
if options.Status != "" {
t.Fatalf("status = %q, want empty all filter", options.Status)
}
if options.RelationType != relationTypeBrother {
t.Fatalf("relation type = %q, want brother", options.RelationType)
}
}
func TestRelationshipListWhereValidatesFilters(t *testing.T) {
whereSQL, args, err := relationshipListWhere("lalu", cpListOptions{RelationType: relationTypeSister, Status: "active"})
if err != nil {
t.Fatalf("relationshipListWhere() error = %v", err)
}
if !strings.Contains(whereSQL, "r.app_code = ?") ||
!strings.Contains(whereSQL, "r.relation_type = ?") ||
!strings.Contains(whereSQL, "r.status = ?") {
t.Fatalf("relationship where sql missing filters: %s", whereSQL)
}
wantArgs := []any{"lalu", relationTypeSister, statusActive}
if len(args) != len(wantArgs) {
t.Fatalf("args len = %d, want %d: %#v", len(args), len(wantArgs), args)
}
for index := range wantArgs {
if args[index] != wantArgs[index] {
t.Fatalf("args[%d] = %#v, want %#v", index, args[index], wantArgs[index])
}
}
if _, _, err := relationshipListWhere("lalu", cpListOptions{RelationType: "enemy"}); !errors.Is(err, ErrInvalidArgument) {
t.Fatalf("invalid relation type error = %v, want ErrInvalidArgument", err)
}
if _, _, err := relationshipListWhere("lalu", cpListOptions{Status: "pending"}); !errors.Is(err, ErrInvalidArgument) {
t.Fatalf("invalid relationship status error = %v, want ErrInvalidArgument", err)
}
}
func TestApplicationListWhereValidatesApplicationStatuses(t *testing.T) {
whereSQL, args, err := applicationListWhere("lalu", cpListOptions{RelationType: relationTypeCP, Status: "pending"})
if err != nil {
t.Fatalf("applicationListWhere() error = %v", err)
}
if !strings.Contains(whereSQL, "a.relation_type = ?") || !strings.Contains(whereSQL, "a.status = ?") {
t.Fatalf("application where sql missing filters: %s", whereSQL)
}
if len(args) != 3 || args[0] != "lalu" || args[1] != relationTypeCP || args[2] != "pending" {
t.Fatalf("application args mismatch: %#v", args)
}
if _, _, err := applicationListWhere("lalu", cpListOptions{Status: "active"}); !errors.Is(err, ErrInvalidArgument) {
t.Fatalf("invalid application status error = %v, want ErrInvalidArgument", err)
}
}
func TestRelationshipDurationDaysIsInclusive(t *testing.T) {
const formedAtMS int64 = 1700000000000
if got := relationshipDurationDays(formedAtMS, 0, formedAtMS); got != 1 {
t.Fatalf("same moment duration = %d, want 1", got)
}
if got := relationshipDurationDays(formedAtMS, 0, formedAtMS+dayMS*2+1); got != 3 {
t.Fatalf("third day duration = %d, want 3", got)
}
if got := relationshipDurationDays(formedAtMS, formedAtMS+dayMS, formedAtMS+dayMS*9); got != 2 {
t.Fatalf("ended relationship duration = %d, want 2", got)
}
if got := relationshipDurationDays(formedAtMS, formedAtMS-1, formedAtMS+dayMS); got != 0 {
t.Fatalf("invalid ended duration = %d, want 0", got)
}
}
func TestCPGiftSnapshotEmpty(t *testing.T) {
if !((&cpGiftSnapshotDTO{}).empty()) {
t.Fatalf("zero gift should be empty")
}
gift := cpGiftSnapshotDTO{GiftValue: 100}
if gift.empty() {
t.Fatalf("gift with value should not be empty")
}
}
func relationInput(relationType string, maxCount int32) relationDTO {
return relationDTO{
RelationType: relationType,
MaxCountPerUser: maxCount,
ApplicationExpireHours: defaultExpireHours,
Status: statusActive,
Levels: []levelDTO{
{Level: 1, IntimacyThreshold: 0, Status: statusActive},
{Level: 2, IntimacyThreshold: 10_000, Status: statusActive},
{Level: 3, IntimacyThreshold: 30_000, Status: statusActive},
{Level: 4, IntimacyThreshold: 60_000, Status: statusActive},
{Level: 5, IntimacyThreshold: 100_000, Status: statusActive},
},
}
}