初始化
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
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) + "<script>alert(1)</script>")},
|
||||
{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, `<?xml version="1.0"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/></Types>`, 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, `<?xml version="1.0"?><Types/>`, nil)
|
||||
if _, err := extractDOCX(fake); err == nil {
|
||||
t.Fatal("expected ZIP with fake DOCX structure to be rejected")
|
||||
}
|
||||
|
||||
macro := makeTestDOCX(t, `<?xml version="1.0"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/></Types>`, 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": `<?xml version="1.0"?><w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body><w:p><w:r><w:t>第一章 开始</w:t></w:r></w:p><w:p><w:r><w:t>这是正文</w:t></w:r></w:p></w:body></w:document>`,
|
||||
}
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user