Files
llmgw/internal/sim/cache_test.go
T
ilkerandClaude Opus 5 e07bc46c57
CI / test (push) Has been cancelled
Faz 0: iskelet ve sim-engine
Plan v0.2'nin Faz 0 çıktısı. Yazılan sıraya göre:

- cobra tabanlı CLI iskeleti; server/agent/ctl komutları henüz stub.
- internal/sim: OpenAI uyumlu sahte inference engine. Router'ı GPU olmadan
  gerçekçi koşullarda test edebilmek için gerçek bir engine'in router
  açısından önemli davranışlarını modeller:
    * continuous batching ve KV blok muhasebesi (head-of-line blocking dahil)
    * zincirlenmiş blok hash'leri + LRU ile otomatik prefix cache
    * batch büyüdükçe artan token gecikmesi
    * istemci koptuğunda isteğin düşürülüp blokların bırakılması
    * vLLM metrik adlarıyla /metrics (plan §7.6 engine kontratı)
- Testler: prefix hash zincirlemesi, LRU tahliyesi, iptal propagasyonu,
  kuyruklama, SSE formatı, usage/cached_tokens, metriklerin gerçek
  Prometheus parser'ıyla okunabilirliği.
- Gitea Actions CI: gofmt, vet, race detector.

Modül yolu gitea.mynodes.xyz/ilker/llmgw; `make rename` ile değiştirilebilir.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 01:00:03 +02:00

78 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package sim
import "testing"
func TestBlockHashesZincirleme(t *testing.T) {
// Aynı içerik farklı ön ekten sonra geliyorsa blok hash'i farklı olmalı.
a := BlockHashes(Tokenize("AAAAAAAABBBBBBBB"), 2)
b := BlockHashes(Tokenize("CCCCCCCCBBBBBBBB"), 2)
if len(a) != 2 || len(b) != 2 {
t.Fatalf("beklenen 2 blok, alınan a=%d b=%d", len(a), len(b))
}
if a[1] == b[1] {
t.Error("farklı ön ekten sonra gelen aynı blok aynı hash'i verdi; zincirleme çalışmıyor")
}
}
func TestBlockHashesOnEkKararli(t *testing.T) {
// Blok sınırına hizalı bir ön ek, uzun metinde aynı blok hash'lerini vermeli.
// Hizalama şart: son yarım token farklı olursa onu içeren blok da farklı
// çıkar — gerçek tokenizer'larda da olan sınır etkisi, bu yüzden prefix
// cache hit'i her zaman tam blok cinsinden ölçülür.
const aligned = "merhaba " // 8 bayt = 2 token = blockSize 2 ile 1 tam blok
short := BlockHashes(Tokenize(aligned), 2)
long := BlockHashes(Tokenize(aligned+"dunya nasilsin"), 2)
if len(short) != 1 {
t.Fatalf("beklenen 1 blok, alınan %d", len(short))
}
if short[0] != long[0] {
t.Fatal("hizalı ön ek blok hash'i değişti; ön ek kararlı değil")
}
}
func TestBlockHashesYarimBlokAtilir(t *testing.T) {
// 3 token, blockSize 2 -> 1 tam blok
if got := len(BlockHashes(make([]Token, 3), 2)); got != 1 {
t.Errorf("beklenen 1 blok, alınan %d", got)
}
if got := len(BlockHashes(make([]Token, 1), 2)); got != 0 {
t.Errorf("tam blok yokken blok üretildi: %d", got)
}
}
func TestPrefixCacheKesintisizOnEk(t *testing.T) {
c := NewPrefixCache(10)
h := []BlockHash{1, 2, 3, 4}
c.Insert(h)
if n := c.Lookup(h); n != 4 {
t.Fatalf("tam eşleşme beklendi, alınan %d", n)
}
// Ortası eksik: ilk blok hit, sonrası miss olmalı.
if n := c.Lookup([]BlockHash{1, 99, 3}); n != 1 {
t.Errorf("kesintisiz ön ek 1 olmalıydı, alınan %d", n)
}
}
func TestPrefixCacheLRUTahliye(t *testing.T) {
c := NewPrefixCache(2)
c.Insert([]BlockHash{1, 2})
c.Lookup([]BlockHash{1}) // 1'i tazele
c.Insert([]BlockHash{3}) // kapasite aşıldı, en eski (2) düşmeli
if n := c.Lookup([]BlockHash{1}); n != 1 {
t.Error("taze blok tahliye edildi")
}
if n := c.Lookup([]BlockHash{2}); n != 0 {
t.Error("en eski blok tahliye edilmeliydi")
}
}
func TestPrefixCacheKapali(t *testing.T) {
c := NewPrefixCache(0)
c.Insert([]BlockHash{1, 2})
if n := c.Lookup([]BlockHash{1}); n != 0 {
t.Errorf("kapalı cache hit verdi: %d", n)
}
}