qq_bot/handler/rss/parse_test.go

254 lines
7.6 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 rss
import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"git.lxtend.com/lixiangwuxian/qqbot/config"
. "github.com/bytedance/mockey"
. "github.com/smartystreets/goconvey/convey"
)
func init() {
Mock((*config.Config).LoadConfig).Return(nil).Build()
}
// 模拟RSS XML数据
const mockRSSXML = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>测试RSS源</title>
<link>https://example.com</link>
<description>这是一个测试RSS源</description>
<item>
<title>测试文章1</title>
<link>https://example.com/article1</link>
<description>这是第一篇测试文章的描述</description>
<guid>https://example.com/article1</guid>
<author>测试作者</author>
<category>技术</category>
<pubDate>Mon, 01 Jan 2024 00:00:00 GMT</pubDate>
</item>
<item>
<title>测试文章2</title>
<link>https://example.com/article2</link>
<description>这是第二篇测试文章的描述</description>
<guid>https://example.com/article2</guid>
<author>测试作者2</author>
<category>生活</category>
<pubDate>Tue, 02 Jan 2024 00:00:00 GMT</pubDate>
</item>
</channel>
</rss>`
func TestParseRssFeed(t *testing.T) {
Convey("TestParseRssFeed", t, func() {
Convey("测试正常RSS解析", func() {
// 创建模拟HTTP服务器
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
w.Header().Set("Content-Type", "application/rss+xml")
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(mockRSSXML)))
w.WriteHeader(http.StatusOK)
return
}
if r.Method == "GET" {
w.Header().Set("Content-Type", "application/rss+xml")
w.WriteHeader(http.StatusOK)
w.Write([]byte(mockRSSXML))
return
}
}))
defer server.Close()
// 测试解析功能
items, err := ParseRssFeed(server.URL)
So(err, ShouldBeNil)
So(len(items), ShouldEqual, 2)
// 验证第一个条目
// So(items[0].Title, ShouldEqual, "测试文章1")
// So(items[0].Link, ShouldEqual, "https://example.com/article1")
// So(items[0].Description, ShouldEqual, "这是第一篇测试文章的描述")
// So(items[0].GUID, ShouldEqual, "https://example.com/article1")
// So(items[0].Author, ShouldEqual, "测试作者")
// So(items[0].Category, ShouldEqual, "技术")
// So(items[0].Hash, ShouldNotBeEmpty)
// // 验证第二个条目
// So(items[1].Title, ShouldEqual, "测试文章2")
// So(items[1].Link, ShouldEqual, "https://example.com/article2")
// So(items[1].Description, ShouldEqual, "这是第二篇测试文章的描述")
// So(items[1].GUID, ShouldEqual, "https://example.com/article2")
// So(items[1].Author, ShouldEqual, "测试作者2")
// So(items[1].Category, ShouldEqual, "生活")
// So(items[1].Hash, ShouldNotBeEmpty)
// 验证哈希值不同
So(items[0].Hash, ShouldNotEqual, items[1].Hash)
fmt.Printf("成功解析RSS源共%d个条目\n", len(items))
for i, item := range items {
fmt.Printf("条目%d: %s - %s\n", i+1, item.Title, item.Link)
}
})
Convey("测试RSS源大小限制", func() {
// 创建超大内容的模拟服务器
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
w.Header().Set("Content-Type", "application/rss+xml")
w.Header().Set("Content-Length", "20971520") // 20MB
w.WriteHeader(http.StatusOK)
return
}
}))
defer server.Close()
_, err := ParseRssFeed(server.URL)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "超出限制")
})
Convey("测试无效RSS源状态码", func() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer server.Close()
_, err := ParseRssFeed(server.URL)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "RSS源无效: 404")
})
Convey("测试无效XML格式", func() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
w.Header().Set("Content-Type", "application/rss+xml")
w.Header().Set("Content-Length", "100")
w.WriteHeader(http.StatusOK)
return
}
if r.Method == "GET" {
w.Header().Set("Content-Type", "application/rss+xml")
w.WriteHeader(http.StatusOK)
w.Write([]byte("这不是有效的XML"))
return
}
}))
defer server.Close()
_, err := ParseRssFeed(server.URL)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "解析RSS数据失败")
})
})
}
func TestCheckRssFeed(t *testing.T) {
Convey("TestCheckRssFeed", t, func() {
Convey("测试有效RSS源检查", func() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/rss+xml")
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
err := CheckRssFeed(server.URL)
So(err, ShouldBeNil)
})
Convey("测试无效Content-Type", func() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
err := CheckRssFeed(server.URL)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "RSS源无效: text/html")
})
Convey("测试无效状态码", func() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer server.Close()
err := CheckRssFeed(server.URL)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "RSS源无效: 500")
})
})
}
func TestRssItemHash(t *testing.T) {
Convey("TestRssItemHash", t, func() {
Convey("测试相同内容生成相同哈希", func() {
content1 := "测试标题测试链接测试描述"
content2 := "测试标题测试链接测试描述"
// 模拟哈希生成过程
hash1 := fmt.Sprintf("%x", []byte(content1))
hash2 := fmt.Sprintf("%x", []byte(content2))
So(hash1, ShouldEqual, hash2)
})
Convey("测试不同内容生成不同哈希", func() {
content1 := "测试标题1测试链接1测试描述1"
content2 := "测试标题2测试链接2测试描述2"
hash1 := fmt.Sprintf("%x", []byte(content1))
hash2 := fmt.Sprintf("%x", []byte(content2))
So(hash1, ShouldNotEqual, hash2)
})
})
}
func TestParseRealRSSFile(t *testing.T) {
Convey("TestParseRealRSSFile", t, func() {
Convey("测试解析真实的RSS文件", func() {
// 创建一个本地文件服务器
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
w.Header().Set("Content-Type", "application/rss+xml")
w.Header().Set("Content-Length", "100000") // 设置一个合理的大小
w.WriteHeader(http.StatusOK)
return
}
if r.Method == "GET" {
// 读取test.xml文件
content, err := os.ReadFile("test.xml")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/rss+xml")
w.WriteHeader(http.StatusOK)
w.Write(content)
return
}
}))
defer server.Close()
// 测试解析功能
items, err := ParseRssFeed(server.URL)
So(err, ShouldBeNil)
So(len(items), ShouldBeGreaterThan, 0)
fmt.Printf("成功解析真实RSS源共%d个条目\n", len(items))
for i, item := range items {
if i < 3 { // 只显示前3个条目
fmt.Printf("条目%d: %s - %s\n", i+1, item.Title, item.Link)
}
}
})
})
}