File size: 2,688 Bytes
6d60378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package server

import (
	"math"
	"testing"
	"time"
)

// tokensPerSecond:分母应是「生成耗时」= 端到端 - TTFB(issue #34)。
//
// 这条测试的价值在于把"没有观测就不扣"这一条钉住:非流式回复没有首个 data 帧,
// 若实现改成"没测到就按某个默认 TTFB 扣",速率会虚高,而单看代码很难发现。
func TestTokensPerSecond(t *testing.T) {
	cases := []struct {
		name      string
		tokens    int64
		total     time.Duration
		ttfb      time.Duration
		want      float64
		wantOk    bool
		tolerance float64
	}{
		{"无 TTFB 观测(非流式)按端到端算", 100, 2 * time.Second, 0, 50, true, 0.01},
		{"扣掉 TTFB:1200ms 里等了 200ms", 100, 1200 * time.Millisecond, 200 * time.Millisecond, 100, true, 0.01},
		{"TTFB 占总耗时一半", 50, time.Second, 500 * time.Millisecond, 100, true, 0.01},
		{"TTFB 超过总耗时 → 退回端到端,不得负/零分母", 100, 100 * time.Millisecond, 500 * time.Millisecond, 1000, true, 0.01},
		{"TTFB 恰好等于总耗时 → 退回端到端", 100, 100 * time.Millisecond, 100 * time.Millisecond, 1000, true, 0.01},
		{"token 为负哨兵(观测缺失)", -1, time.Second, 100 * time.Millisecond, 0, false, 0},
		{"零耗时", 10, 0, 0, 0, false, 0},
		{"零 token 但有效耗时", 0, time.Second, 0, 0, true, 0.01},
	}
	for _, c := range cases {
		got, ok := tokensPerSecond(c.tokens, c.total, c.ttfb)
		if ok != c.wantOk {
			t.Errorf("%s: ok=%v want %v", c.name, ok, c.wantOk)
			continue
		}
		if !ok {
			continue
		}
		if math.Abs(got-c.want) > c.tolerance {
			t.Errorf("%s: got %.3f want %.3f", c.name, got, c.want)
		}
	}
}

// TestTokensPerSecondTTFBMonotonic 语义回归:TTFB 越大,扣减越多、速率越高。
// 这正是 issue #34 的核心——修复前两者相等(TTFB 完全不影响结果)。
func TestTokensPerSecondTTFBMonotonic(t *testing.T) {
	const tok = 200
	total := 2 * time.Second
	without, _ := tokensPerSecond(tok, total, 0)
	with200, _ := tokensPerSecond(tok, total, 200*time.Millisecond)
	with800, _ := tokensPerSecond(tok, total, 800*time.Millisecond)

	if !(without < with200 && with200 < with800) {
		t.Fatalf("速率应随 TTFB 增大而上升:ttfb=0 -> %.2f, 200ms -> %.2f, 800ms -> %.2f",
			without, with200, with800)
	}
	// 修复前的公式正是 without(等于端到端口径),确认它确实更低。
	if math.Abs(without-100) > 0.01 {
		t.Errorf("无 TTFB 时应等于端到端口径 100,得到 %.2f", without)
	}
	if math.Abs(with200-111.11) > 0.05 {
		t.Errorf("扣 200ms 后应约 111.11,得到 %.2f", with200)
	}
}