96d97e8964
A ZIM title carries a leading capital and the utterance does not: /A/фотосинтез is a 404 and /A/Фотосинтез is a 200. TitleCandidates tries the spoken form first, so a title that begins lowercase on purpose keeps its chance. That takes the measurement from four right to five, and the fifth is the one that mattered. "столица Франции" returned "Список столиц Олимпийских игр" and now returns Париж, through a title redirect the ZIM already held. The 2026-08-05 measurement named that case as the one no lexical signal could reach. Retrieval by title reaches it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013ptwopxyo3Z2kwFckHkLvN
70 lines
2.1 KiB
Go
70 lines
2.1 KiB
Go
package kiwix
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestLiveTopicBeatsTheSentence — the measurement V-668 turned on, kept as a
|
|
// test so the claim can be re-run rather than believed.
|
|
//
|
|
// It prints the article the old path returned and the article the new one
|
|
// returns, for the same question. It asserts nothing about which is better,
|
|
// because "is this the right article" is a human's call. It fails only if the
|
|
// two paths agree on every case, which would mean the change does nothing.
|
|
//
|
|
// MAVEN_KIWIX_URL=http://127.0.0.1:8034 make t PKG=./internal/kiwix/ RUN=TestLive V=1
|
|
func TestLiveTopicBeatsTheSentence(t *testing.T) {
|
|
base := os.Getenv("MAVEN_KIWIX_URL")
|
|
if base == "" {
|
|
t.Skip("MAVEN_KIWIX_URL unset — point it at the kiwix-server host port")
|
|
}
|
|
const book = "wikipedia_ru_all_maxi_2026-02"
|
|
c := New(base)
|
|
questions := []string{
|
|
"что такое TCP?",
|
|
"что такое фотосинтез",
|
|
"кто такой Линус Торвальдс?",
|
|
"кто написал Войну и мир",
|
|
"что такое чёрная дыра",
|
|
"почему небо голубое",
|
|
"почему трава зелёная",
|
|
"столица Франции",
|
|
}
|
|
moved := 0
|
|
for _, q := range questions {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
|
before := firstTitle(ctx, c, q, book)
|
|
topic := Topic(q)
|
|
after := ""
|
|
for _, cand := range TitleCandidates(topic) {
|
|
if page, err := c.Article(ctx, TitlePath(book, cand), 400); err == nil && page.Text != "" {
|
|
after = page.Title + " (by title)"
|
|
break
|
|
}
|
|
}
|
|
if after == "" {
|
|
after = firstTitle(ctx, c, topic, book)
|
|
}
|
|
cancel()
|
|
if before != after {
|
|
moved++
|
|
}
|
|
t.Logf("%-30s before=%-34q after=%q", q, before, after)
|
|
}
|
|
t.Logf("%d of %d questions reach a different article", moved, len(questions))
|
|
if moved == 0 {
|
|
t.Error("the topic path returns exactly what the sentence path returned")
|
|
}
|
|
}
|
|
|
|
func firstTitle(ctx context.Context, c *Client, pattern, book string) string {
|
|
hits, err := c.Search(ctx, pattern, book, 3)
|
|
if err != nil || len(hits) == 0 {
|
|
return "(nothing)"
|
|
}
|
|
return hits[0].Title
|
|
}
|