Files
jbergner bcfbef390f
release-tag / release-image (push) Failing after 2m44s
RC-7
2026-08-11 16:58:07 +02:00

78 lines
2.4 KiB
Go

package server
import (
"context"
"fmt"
"testing"
"time"
)
func TestGuessLotteryDrawSelectsExactQuota(t *testing.T) {
l := newGuessLottery(nil)
const total = 40
const quota = 9
b := &lotteryBucket{max: quota, end: time.Now().Add(time.Second), keys: make(map[string]struct{})}
for i := 0; i < total; i++ {
ticket := &lotteryTicket{key: fmt.Sprintf("c-%d|0", i), ctx: context.Background(), result: make(chan lotteryDelivery, 1)}
b.tickets = append(b.tickets, ticket)
b.keys[ticket.key] = struct{}{}
}
l.buckets["test"] = b
l.draw("test", "task-test")
selected := 0
for _, ticket := range b.tickets {
if (<-ticket.result).result.Selected {
selected++
}
}
if selected != quota {
t.Fatalf("selected %d tickets, want %d", selected, quota)
}
}
func TestGuessLotteryCanceledTicketDoesNotConsumeQuota(t *testing.T) {
l := newGuessLottery(nil)
ctx, cancel := context.WithCancel(context.Background())
cancel()
canceled := &lotteryTicket{key: "canceled", ctx: ctx, result: make(chan lotteryDelivery, 1)}
alive := &lotteryTicket{key: "alive", ctx: context.Background(), result: make(chan lotteryDelivery, 1)}
l.buckets["test"] = &lotteryBucket{max: 1, tickets: []*lotteryTicket{canceled, alive}, keys: map[string]struct{}{"canceled": {}, "alive": {}}}
l.draw("test", "task-test")
if got := (<-alive.result).result.Selected; !got {
t.Fatal("live ticket should receive the available slot")
}
}
func TestWeightedBeaconDrawIsDeterministicAndRewardsBoostedPath(t *testing.T) {
tickets := []*lotteryTicket{
{key: "a", path: "PULSE"}, {key: "b", path: "FLUX"}, {key: "c", path: "PULSE"},
{key: "d", path: "ORBIT"}, {key: "e", path: "PULSE"}, {key: "f", path: "FLUX"},
}
a := weightedBeaconDraw(tickets, 3, "PULSE", 2, "deadbeef", "bucket")
b := weightedBeaconDraw(tickets, 3, "PULSE", 2, "deadbeef", "bucket")
if len(a) != len(b) {
t.Fatal("draw length mismatch")
}
count := 0
for i := range a {
if a[i] != b[i] {
t.Fatalf("draw is not deterministic at %d", i)
}
if a[i] {
count++
}
}
if count != 3 {
t.Fatalf("selected %d, want 3", count)
}
}
func TestBeaconTargetRoundIsStrictlyAfterWindow(t *testing.T) {
info := drandInfo{Period: 3, GenesisTime: 1000}
end := time.Unix(1006, 0).UTC() // exact round boundary
r := targetRound(info, end)
if !roundTime(info, r).After(end) {
t.Fatalf("round %d at %s must be after %s", r, roundTime(info, r), end)
}
}