254 lines
7.6 KiB
Go
254 lines
7.6 KiB
Go
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)
|
||
}
|
||
}
|
||
})
|
||
})
|
||
}
|