package service
import (
"archive/zip"
"bytes"
"strings"
"testing"
)
func TestParseDramaSourceRejectsDisguisedAndExecutableContent(t *testing.T) {
cases := []struct {
name string
filename string
data []byte
raw string
}{
{name: "pdf renamed txt", filename: "novel.txt", data: []byte("%PDF-1.7\ncontent")},
{name: "zip renamed txt", filename: "novel.txt", data: []byte{'P', 'K', 3, 4, 1, 2, 3}},
{name: "html after long prefix", filename: "novel.txt", data: []byte(strings.Repeat("正文", 3000) + "")},
{name: "script pasted", raw: "小说正文\njavascript:alert(1)"},
{name: "binary pasted", raw: "正文\x00内容"},
}
for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
if _, _, err := parseDramaSource(test.filename, test.data, test.raw); err == nil {
t.Fatal("expected unsafe import to be rejected")
}
})
}
}
func TestExtractDOCXReadsParagraphsAndValidatesWordPackage(t *testing.T) {
valid := makeTestDOCX(t, ``, nil)
text, err := extractDOCX(valid)
if err != nil {
t.Fatalf("extractDOCX returned error: %v", err)
}
if !strings.Contains(text, "第一章 开始") || !strings.Contains(text, "这是正文") {
t.Fatalf("unexpected extracted text: %q", text)
}
fake := makeTestDOCX(t, ``, nil)
if _, err := extractDOCX(fake); err == nil {
t.Fatal("expected ZIP with fake DOCX structure to be rejected")
}
macro := makeTestDOCX(t, ``, map[string]string{"word/vbaProject.bin": "macro"})
if _, err := extractDOCX(macro); err == nil {
t.Fatal("expected macro-enabled package to be rejected")
}
}
func TestSplitDramaChaptersPreservesOriginalText(t *testing.T) {
source := "作品说明\n\n第一章 初见\n正文一\n\n第二章 重逢\n正文二"
chapters := splitDramaChapters(source)
if len(chapters) != 2 {
t.Fatalf("expected 2 chapters, got %d", len(chapters))
}
joined := strings.TrimSpace(chapters[0].Content + "\n\n" + chapters[1].Content)
if joined != source {
t.Fatalf("chapter splitting lost or duplicated text:\nwant: %q\n got: %q", source, joined)
}
if chapters[0].Title != "第一章 初见" || chapters[1].Title != "第二章 重逢" {
t.Fatalf("unexpected chapter titles: %#v", chapters)
}
if chapters := splitDramaChapters("没有章节标题的完整正文"); chapters != nil {
t.Fatalf("text without chapter titles must require single-episode confirmation: %#v", chapters)
}
}
func makeTestDOCX(t *testing.T, contentTypes string, extras map[string]string) []byte {
t.Helper()
var buffer bytes.Buffer
writer := zip.NewWriter(&buffer)
files := map[string]string{
"[Content_Types].xml": contentTypes,
"word/document.xml": `第一章 开始这是正文`,
}
for name, content := range extras {
files[name] = content
}
for name, content := range files {
entry, err := writer.Create(name)
if err != nil {
t.Fatal(err)
}
if _, err = entry.Write([]byte(content)); err != nil {
t.Fatal(err)
}
}
if err := writer.Close(); err != nil {
t.Fatal(err)
}
return buffer.Bytes()
}