package main
import (
"fmt"
"strconv"
"strings"
"testing"
c "github.com/Azareal/Gosora/common"
)
func TestPreparser(t *testing.T) {
miscinit(t)
if !c.PluginsInited {
c.InitPlugins()
}
l := &METriList{nil}
// Note: The open tag is evaluated without knowledge of the close tag for efficiency and simplicity, so the parser autofills the associated close tag when it finds an open tag without a partner
l.Add("", "")
l.Add(" ", "")
l.Add(" hi", "hi")
l.Add("hi ", "hi")
l.Add("hi", "hi")
l.Add(":grinning:", "π")
l.Add(":grinning: :grinning:", "π π")
l.Add(" :grinning: ", "π")
l.Add(": :grinning: :", ": π :")
l.Add("::grinning::", ":π:")
//l.Add("d:grinning:d", "d:grinning:d") // todo
l.Add("d :grinning: d", "d π d")
l.Add("π", "π")
l.Add(" ", "")
l.Add("
", "")
l.Add("
", "")
l.Add("
", "")
l.Add("<", "<")
l.Add(">", ">")
l.Add("", "<meow>")
l.Add("<", "<")
l.Add("&", "&")
// Note: strings.TrimSpace strips newlines, if there's nothing before or after them
l.Add(" ", "")
l.Add(" ", "")
l.Add("\\n", "\n", "")
l.Add("\\n\\n", "\n\n", "")
l.Add("\\n\\n\\n", "\n\n\n", "")
l.Add("\\r\\n", "\r\n", "") // Windows style line ending
l.Add("\\n\\r", "\n\r", "")
l.Add("ho ho", "ho\n\nho")
l.Add("ho ho", "ho\n\nho")
l.Add("ho\\nho", "ho\nho", "ho\nho")
l.Add("ho\\n\\nho", "ho\n\nho", "ho\n\nho")
//l.Add("ho\\n\\n\\n\\nho", "ho\n\n\n\nho", "ho\n\n\nho")
l.Add("ho\\r\\nho", "ho\r\nho", "ho\nho") // Windows style line ending
l.Add("ho\\n\\rho", "ho\n\rho", "ho\nho")
l.Add(" ", " ")
l.Add("hi ", "hi ")
l.Add("h ", "h ")
l.Add("hi ", "hi")
l.Add("hi", "hi")
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi ", "hi") // Grammarly fix
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi
", "<div>hi</div>")
l.Add("hi ", "hi") // This is stripped since the editor (Trumbowyg) likes blasting useless spans
l.Add("hi ", "hi")
l.Add("hi ", "hi")
l.Add(">hi ", ">hi")
l.Add("hi", "hi ")
l.Add("hi ", "hi</b>")
l.Add("", "</b>")
l.Add("", "</del>")
l.Add("", "</strong>")
l.Add("", " ")
l.Add("hi", "hi")
l.Add("hi", "hi")
l.Add("hi ", "hi")
l.Add(" ", "")
l.Add(" ", "")
l.Add(" ", "")
l.Add(" ", "")
l.Add(" ", " ")
l.Add("t ", "t ")
l.Add("t ", "t ")
l.Add("t ", "t ")
l.Add("<>>", "<></>")
l.Add("><>", "</><>")
l.Add("<>", "<>")
l.Add(">", "</>")
l.Add(" hi
", "hi")
l.Add("
", "")
l.Add("hi ", "hi ")
l.Add("hi ", "hi ")
l.Add("hi ", "<meow>hi</meow> ")
l.Add("\\hi ", "<blockquote>hi</blockquote>")
//l.Add("\\\\hi ", "\\<meow>hi</meow> ") // TODO: Double escapes should print a literal backslash
//l.Add("<blockquote>hi</blockquote>", "<blockquote>hi</blockquote>") // TODO: Stop double-entitising this
l.Add("\\hi \\hi ", "<blockquote>hi</blockquote><blockquote>hi</blockquote>")
l.Add("\\Admin ", "<a itemprop="author">Admin</a>")
l.Add("\\Admin ", "<a itemprop="author">Admin</a> ")
l.Add("\n\\Admin \n", "<a itemprop="author">Admin</a> ")
l.Add("tt\n\\Admin \ntt", "tt\n<a itemprop="author">Admin</a> \ntt")
l.Add("@", "@")
l.Add("@Admin", "@1")
l.Add("@Bah", "@Bah")
l.Add(" @Admin", "@1")
l.Add("\n@Admin", "@1")
l.Add("@Admin\n", "@1")
l.Add("@Admin\ndd", "@1\ndd")
l.Add("d@Admin", "d@Admin")
l.Add("\\@Admin", "@Admin")
l.Add("@ε
ζ°", "@ε
ζ°")
// TODO: More tests for unicode names?
//l.Add("\\\\@Admin", "@1")
//l.Add("byte 0", string([]byte{0}), "")
l.Add("byte 'a'", string([]byte{'a'}), "a")
//l.Add("byte 255", string([]byte{255}), "")
//l.Add("rune 0", string([]rune{0}), "")
// TODO: Do a test with invalid UTF-8 input
for _, item := range l.Items {
if res := c.PreparseMessage(item.Msg); res != item.Expects {
if item.Name != "" {
t.Error("Name: ", item.Name)
}
t.Error("Testing string '" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'")
//t.Error("Ouput in bytes:", []byte(res))
t.Error("Expected:", "'"+item.Expects+"'")
}
}
}
func TestParser(t *testing.T) {
miscinit(t)
if !c.PluginsInited {
c.InitPlugins()
}
l := &METriList{nil}
url := "github.com/Azareal/Gosora"
eurl := "" + url + " "
l.Add("", "")
l.Add("haha", "haha")
l.Add(":P", "π")
l.Add(" :P ", " π ")
l.Add(":p", "π")
l.Add("d:p", "d:p")
l.Add(":pd", "πd")
l.Add(":pdd", "πdd")
l.Add(":pddd", "πddd")
l.Add(":p d", "π d")
l.Add(":p dd", "π dd")
l.Add(":p ddd", "π ddd")
//l.Add(":p:p:p", "πππ")
l.Add(":p:p:p", "π:p:p")
l.Add(":p :p", "π π")
l.Add(":p :p :p", "π π π")
l.Add(":p :p :p :p", "π π π π")
l.Add(":p :p :p", "π π π")
l.Add("word:p", "word:p")
l.Add("word:pword", "word:pword")
l.Add(":pword", "πword") // TODO: Change the semantics on this to detect the succeeding character?
l.Add("word :p", "word π")
l.Add(":p word", "π word")
l.Add("t ", "t ")
l.Add("//", "//")
l.Add("http://", "[Invalid URL] ")
l.Add("https://", "[Invalid URL] ")
l.Add("ftp://", "[Invalid URL] ")
l.Add("git://", "[Invalid URL] ")
l.Add("ssh://", "ssh://")
l.Add("// ", "// ")
l.Add("// //", "// //")
l.Add("// // //", "// // //")
l.Add("http:// ", "[Invalid URL] ")
l.Add("https:// ", "[Invalid URL] ")
l.Add("ftp:// ", "[Invalid URL] ")
l.Add("git:// ", "[Invalid URL] ")
l.Add("ssh:// ", "ssh:// ")
l.Add("//t", "t ")
l.Add("// t", "// t")
l.Add("http:// t", "[Invalid URL] t")
l.Add("g", "g")
l.Add("g/", "//") // todo: fix this
l.Add("/g", "/g")
l.Add("/gg", "/gg")
l.Add("/g/", "/g/")
l.Add("hi", "hi")
l.Add("hit", "hit")
l.Add("hit:", "hit:")
l.Add("hit:/", "/ ") // todo: fix this
l.Add("hit://", " ") // todo: fix this
l.Add("hit://t", "t ") // todo: fix this
l.Add("h", "h")
l.Add("ht", "ht")
l.Add("htt", "htt")
l.Add("http", "http")
l.Add("http:", "http:")
//t l.Add("http:/", "http:/")
//t l.Add("http:/d", "http:/d")
l.Add("http:d", "http:d")
l.Add("https:", "https:")
l.Add("ftp:", "ftp:")
l.Add("git:", "git:")
l.Add("ssh:", "ssh:")
l.Add("http", "http")
l.Add("https", "https")
l.Add("ftp", "ftp")
l.Add("git", "git")
l.Add("ssh", "ssh")
l.Add("ht", "ht")
l.Add("htt", "htt")
l.Add("ft", "ft")
l.Add("gi", "gi")
l.Add("ss", "ss")
l.Add("haha\nhaha\nhaha", "haha haha haha")
l.Add("//"+url, eurl)
l.Add("//a", "a ")
l.Add(" //a", " a ")
l.Add("//a ", "a ")
l.Add(" //a ", " a ")
l.Add("d //a ", "d a ")
l.Add("ddd ddd //a ", "ddd ddd a ")
l.Add("https://"+url, ""+url+" ")
l.Add("https://t", "t ")
l.Add("http://"+url, ""+url+" ")
l.Add("#http://"+url, "#http://"+url)
l.Add("@http://"+url, "[Invalid Profile] ttp://"+url)
l.Add("//"+url+"\n", ""+url+" ")
l.Add("\n//"+url, " "+eurl)
l.Add("\n//"+url+"\n", " "+eurl+" ")
l.Add("\n//"+url+"\n\n", " "+eurl+" ")
l.Add("//"+url+"\n//"+url, eurl+" "+eurl)
l.Add("//"+url+" //"+url, eurl+" "+eurl)
l.Add("//"+url+" //"+url, eurl+" "+eurl)
//l.Add("//"+url+"//"+url, eurl+""+eurl)
//l.Add("//"+url+"|//"+url, eurl+"|"+eurl)
l.Add("//"+url+"|//"+url, "[Invalid URL] |//"+url)
l.Add("//"+url+"//"+url, ""+url+"//"+url+" ")
l.Add("//"+url+"\n\n//"+url, eurl+" "+eurl)
pre2 := c.Config.SslSchema
c.Config.SslSchema = true
local := func(u string) {
s := "//" + c.Site.URL
fs := "http://" + c.Site.URL
if c.Config.SslSchema {
s = "https:" + s
fs = "https://" + c.Site.URL
}
l.Add("//"+u, ""+c.Site.URL+" ")
// TODO: Strip redundant slashes?
l.Add("//"+u+"/", ""+c.Site.URL+"/ ")
l.Add("//"+u+"//", ""+c.Site.URL+"// ")
l.Add("//"+u+"\n", ""+c.Site.URL+" ")
l.Add("//"+u+"\n//"+u, ""+c.Site.URL+" "+c.Site.URL+" ")
l.Add("http://"+u, ""+c.Site.URL+" ")
l.Add("https://"+u, ""+c.Site.URL+" ")
l.Add("//"+u+"/attachs/sha256hash.webm?sid=1&stype=forums", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.webm", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.webm?sid=1", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.webm?stype=forums", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.mp3?sid=1&stype=forums", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.mp3", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.mp3?sid=1", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.mp3?stype=forums", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.png?sid=1&stype=forums", " ")
l.Add("//"+u+"/attachs/sha256hash?sid=1&stype=forums", "[Invalid URL] ")
l.Add("//"+u+"/attachs/s?sid=1&stype=forums", "[Invalid URL] ")
l.Add("//"+u+"/attachs/?sid=1&stype=forums", "[Invalid URL] ")
l.Add("//"+u+"/attachs/sha256hash.?sid=1&stype=forums", "[Invalid URL] ")
l.Add("//"+u+"/attachs?sid=1&stype=forums", "[Invalid URL] ")
l.Add("//"+u+"/attachs/sha256hash.png", " ")
l.Add("//"+u+"/attachs/sha256hash.png?sid=1", " ")
l.Add("//"+u+"/attachs/sha256hash.png?stype=forums", " ")
//l.Add("//"+u+"/attachs/sha256hash.txt?sid=1&stype=forums", "Attachment ")
l.Add("//"+u+"/attachs/sha256hash.txt?sid=1&stype=forums", ""+fs+"/attachs/sha256hash.txt
")
l.Add("//example.com/image.png", " ")
l.Add("https://example.com/image.png", " ")
l.Add("http://example.com/image.png", " ")
}
local("localhost")
local("127.0.0.1")
local("[::1]")
l.Add("https://www.youtube.com/watch?v=lalalalala", "https://www.youtube.com/watch?v=lalalalala ")
l.Add("https://www.youtube.com/watch?v=lalalalala&t=30s", "https://www.youtube.com/watch?v=lalalalala&t=30s ")
l.Add("https://www.youtube.com/watch?v=lalalalala&t=1s", "https://www.youtube.com/watch?v=lalalalala ")
l.Add("https://www.youtube.com/watch?v=lalalalala&t=1", "https://www.youtube.com/watch?v=lalalalala ")
//l.Add("https://www.youtube.com/watch?v=;","https://www.youtube.com/watch ")
l.Add("https://www.youtube.com/watch?v=d;", "https://www.youtube.com/watch?v=d ")
l.Add("https://www.youtube.com/watch?v=d;d", "https://www.youtube.com/watch?v=d ")
l.Add("https://www.youtube.com/watch?v=alert()", "[Invalid URL] ()")
l.Add("https://www.youtube.com/watch?v=alert()()", "[Invalid URL] ()()")
l.Add("https://www.youtube.com/watch?v=js:alert()", "[Invalid URL] ()")
l.Add("https://www.youtube.com/watch?v='+><+'", "[Invalid URL] '+><+'")
l.Add("https://www.youtube.com/watch?v='+onready='alert(\"\")'+'", "[Invalid URL] '+onready='alert(\"\")'+'")
l.Add(" https://www.youtube.com/watch?v=lalalalala", " https://www.youtube.com/watch?v=lalalalala ")
l.Add("https://www.youtube.com/watch?v=lalalalala tt", "https://www.youtube.com/watch?v=lalalalala tt")
l.Add("https://www.youtube.com/watch?v=lalalalala&d=haha", "https://www.youtube.com/watch?v=lalalalala ")
l.Add("https://gaming.youtube.com/watch?v=lalalalala", "https://gaming.youtube.com/watch?v=lalalalala ")
l.Add("https://gaming.youtube.com/watch?v=lalalalala&d=haha", "https://gaming.youtube.com/watch?v=lalalalala ")
l.Add("https://youtu.be/lalalalala", "https://youtu.be/lalalalala ")
l.Add("https://m.youtube.com/watch?v=lalalalala", "https://m.youtube.com/watch?v=lalalalala ")
l.Add("https://m.youtube.com/watch?v=lalalalala&d=haha", "https://m.youtube.com/watch?v=lalalalala ")
l.Add("http://www.youtube.com/watch?v=lalalalala", "https://www.youtube.com/watch?v=lalalalala ")
l.Add("//www.youtube.com/watch?v=lalalalala", "https://www.youtube.com/watch?v=lalalalala ")
//l.Add("www.youtube.com/watch?v=lalalalala","https://www.youtube.com/watch?v=lalalalala ")
l.Add("https://www.nicovideo.jp/watch/sm111111", "https://www.nicovideo.jp/watch/sm111111 ")
//l.Add("www.nicovideo.jp/watch/sm111111", "www.nicovideo.jp/watch/sm111111 ")
//l.Add("www.nicovideo.jp/watch/smlalalalala", "www.nicovideo.jp/watch/smlalalalala ")
l.Add("https://www.nicovideo.jp/watch/smlalalalala", "www.nicovideo.jp/watch/smlalalalala ")
l.Add("//www.youtube.com/watch?v=lalalalala&t=30s", "https://www.youtube.com/watch?v=lalalalala&t=30s ")
l.Add("#tid-1", "#tid-1 ")
l.Add("#tid-1#tid-1", "#tid-1 #tid-1")
l.Add("##tid-1", "##tid-1")
l.Add("#@tid-1", "#@tid-1")
l.Add("# #tid-1", "# #tid-1")
l.Add("@ #tid-1", "[Invalid Profile] #tid-1")
l.Add("@#tid-1", "[Invalid Profile] tid-1")
l.Add("@ #tid-@", "[Invalid Profile] #tid-@")
l.Add("#tid-1 #tid-1", "#tid-1 #tid-1 ")
l.Add("#tid-0", "[Invalid Topic] ")
l.Add("https://"+url+"/#tid-1", ""+url+"/#tid-1 ")
l.Add("https://"+url+"/?hi=2", ""+url+"/?hi=2 ")
l.Add("https://"+url+"/?hi=2#t=1", ""+url+"/?hi=2#t=1 ")
l.Add("#fid-1", "#fid-1 ")
l.Add(" #fid-1", " #fid-1 ")
l.Add("#fid-0", "[Invalid Forum] ")
l.Add(" #fid-0", " [Invalid Forum] ")
l.Add("#", "#")
l.Add("# ", "# ")
l.Add(" @", " @")
l.Add(" #", " #")
l.Add("#@", "#@")
l.Add("#@ ", "#@ ")
l.Add("#@1", "#@1")
l.Add("#f", "#f")
l.Add("f#f", "f#f")
l.Add("f#", "f#")
l.Add("#ff", "#ff")
l.Add("#ffffid-0", "#ffffid-0")
//l.Add("#ffffid-0", "#ffffid-0")
l.Add("#nid-0", "#nid-0")
l.Add("#nnid-0", "#nnid-0")
l.Add("@@", "[Invalid Profile] ")
l.Add("@@ @@", "[Invalid Profile] [Invalid Profile] ")
l.Add("@@1", "[Invalid Profile] 1")
l.Add("@#1", "[Invalid Profile] 1")
l.Add("@##1", "[Invalid Profile] #1")
l.Add("@2", "[Invalid Profile] ")
l.Add("@2t", "[Invalid Profile] t")
l.Add("@2 t", "[Invalid Profile] t")
l.Add("@2 ", "[Invalid Profile] ")
l.Add("@2 @2", "[Invalid Profile] [Invalid Profile] ")
l.Add("@1", "@Admin ")
l.Add(" @1", " @Admin ")
l.Add("@1t", "@Admin t")
l.Add("@1 ", "@Admin ")
l.Add("@1 @1", "@Admin @Admin ")
l.Add("@0", "[Invalid Profile] ")
l.Add("@-1", "[Invalid Profile] 1")
// TODO: Fix this hack and make the results a bit more reproducible, push the tests further in the process.
c.GuestUser.Perms.AutoLink = true
for _, item := range l.Items {
if res := c.ParseMessage(item.Msg, 1, "forums", nil, nil); res != item.Expects {
if item.Name != "" {
t.Error("Name: ", item.Name)
}
t.Error("Testing string '" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", "'"+item.Expects+"'")
break
}
}
c.Config.SslSchema = pre2
l = &METriList{nil}
pre := c.Site.URL // Just in case this is localhost...
pre2 = c.Config.SslSchema
c.Site.URL = "example.com"
c.Config.SslSchema = true
l.Add("//"+c.Site.URL, ""+c.Site.URL+" ")
l.Add("//"+c.Site.URL+"\n", ""+c.Site.URL+" ")
l.Add("//"+c.Site.URL+"\n//"+c.Site.URL, ""+c.Site.URL+" "+c.Site.URL+" ")
for _, item := range l.Items {
if res := c.ParseMessage(item.Msg, 1, "forums", nil, nil); res != item.Expects {
if item.Name != "" {
t.Error("Name: ", item.Name)
}
t.Error("Testing string '" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", "'"+item.Expects+"'")
break
}
}
c.Site.URL = pre
c.Config.SslSchema = pre2
c.AddHashLinkType("nnid-", func(sb *strings.Builder, msg string, i *int) {
tid, intLen := c.CoerceIntString(msg[*i:])
*i += intLen
topic, err := c.Topics.Get(tid)
if err != nil || !c.Forums.Exists(topic.ParentID) {
sb.Write(c.InvalidTopic)
return
}
c.WriteURL(sb, c.BuildTopicURL("", tid), "#nnid-"+strconv.Itoa(tid))
})
res := c.ParseMessage("#nnid-1", 1, "forums", nil, nil)
expect := "#nnid-1 "
if res != expect {
t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", "'"+expect+"'")
}
c.AddHashLinkType("longidnameneedtooverflowhack-", func(sb *strings.Builder, msg string, i *int) {
tid, intLen := c.CoerceIntString(msg[*i:])
*i += intLen
topic, err := c.Topics.Get(tid)
if err != nil || !c.Forums.Exists(topic.ParentID) {
sb.Write(c.InvalidTopic)
return
}
c.WriteURL(sb, c.BuildTopicURL("", tid), "#longidnameneedtooverflowhack-"+strconv.Itoa(tid))
})
res = c.ParseMessage("#longidnameneedtooverflowhack-1", 1, "forums", nil, nil)
expect = "#longidnameneedtooverflowhack-1 "
if res != expect {
t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", "'"+expect+"'")
}
}
func TestPaginate(t *testing.T) {
var plist []int
f := func(i, want int) {
expect(t, plist[i] == want, fmt.Sprintf("plist[%d] should be %d not %d", i, want, plist[i]))
}
plist = c.Paginate(1, 1, 5)
expect(t, len(plist) == 1, fmt.Sprintf("len of plist should be 1 not %d", len(plist)))
f(0, 1)
plist = c.Paginate(1, 5, 5)
expect(t, len(plist) == 5, fmt.Sprintf("len of plist should be 5 not %d", len(plist)))
f(0, 1)
f(1, 2)
f(2, 3)
f(3, 4)
f(4, 5)
// TODO: More Paginate() tests
// TODO: Tests for other paginator functions
}