2018-11-22 07:21:43 +00:00
package main
import (
2019-05-22 04:45:07 +00:00
"strconv"
"strings"
2018-11-22 07:21:43 +00:00
"testing"
2019-04-19 08:20:10 +00:00
c "github.com/Azareal/Gosora/common"
2018-11-22 07:21:43 +00:00
)
func TestPreparser ( t * testing . T ) {
2019-07-11 07:20:33 +00:00
miscinit ( t )
if ! c . PluginsInited {
c . InitPlugins ( )
}
2018-11-22 07:21:43 +00:00
var msgList = & 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
msgList . Add ( "" , "" )
msgList . Add ( " " , "" )
msgList . Add ( " hi" , "hi" )
msgList . Add ( "hi " , "hi" )
msgList . Add ( "hi" , "hi" )
msgList . Add ( ":grinning:" , "😀" )
msgList . Add ( "😀" , "😀" )
msgList . Add ( " " , "" )
msgList . Add ( "<p>" , "" )
msgList . Add ( "</p>" , "" )
msgList . Add ( "<p></p>" , "" )
msgList . Add ( "<" , "<" )
msgList . Add ( ">" , ">" )
msgList . Add ( "<meow>" , "<meow>" )
msgList . Add ( "<" , "&lt;" )
msgList . Add ( "&" , "&" )
// Note: strings.TrimSpace strips newlines, if there's nothing before or after them
msgList . Add ( "<br>" , "" )
msgList . Add ( "<br />" , "" )
msgList . Add ( "\\n" , "\n" , "" )
msgList . Add ( "\\n\\n" , "\n\n" , "" )
msgList . Add ( "\\n\\n\\n" , "\n\n\n" , "" )
msgList . Add ( "\\r\\n" , "\r\n" , "" ) // Windows style line ending
msgList . Add ( "\\n\\r" , "\n\r" , "" )
msgList . Add ( "ho<br>ho" , "ho\n\nho" )
msgList . Add ( "ho<br />ho" , "ho\n\nho" )
msgList . Add ( "ho\\nho" , "ho\nho" , "ho\nho" )
msgList . Add ( "ho\\n\\nho" , "ho\n\nho" , "ho\n\nho" )
//msgList.Add("ho\\n\\n\\n\\nho", "ho\n\n\n\nho", "ho\n\n\nho")
msgList . Add ( "ho\\r\\nho" , "ho\r\nho" , "ho\nho" ) // Windows style line ending
msgList . Add ( "ho\\n\\rho" , "ho\n\rho" , "ho\nho" )
msgList . Add ( "<b></b>" , "<strong></strong>" )
msgList . Add ( "<b>hi</b>" , "<strong>hi</strong>" )
2019-04-09 05:33:39 +00:00
msgList . Add ( "<b>h</b>" , "<strong>h</strong>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "<s>hi</s>" , "<del>hi</del>" )
msgList . Add ( "<del>hi</del>" , "<del>hi</del>" )
msgList . Add ( "<u>hi</u>" , "<u>hi</u>" )
msgList . Add ( "<em>hi</em>" , "<em>hi</em>" )
msgList . Add ( "<i>hi</i>" , "<em>hi</em>" )
msgList . Add ( "<strong>hi</strong>" , "<strong>hi</strong>" )
msgList . Add ( "<b><i>hi</i></b>" , "<strong><em>hi</em></strong>" )
msgList . Add ( "<strong><em>hi</em></strong>" , "<strong><em>hi</em></strong>" )
msgList . Add ( "<b><i><b>hi</b></i></b>" , "<strong><em><strong>hi</strong></em></strong>" )
msgList . Add ( "<strong><em><strong>hi</strong></em></strong>" , "<strong><em><strong>hi</strong></em></strong>" )
msgList . Add ( "<div>hi</div>" , "<div>hi</div>" )
msgList . Add ( "<span>hi</span>" , "hi" ) // This is stripped since the editor (Trumbowyg) likes blasting useless spans
msgList . Add ( "<span >hi</span>" , "hi" )
msgList . Add ( "<span style='background-color: yellow;'>hi</span>" , "hi" )
msgList . Add ( "<span style='background-color: yellow;'>>hi</span>" , ">hi" )
msgList . Add ( "<b>hi" , "<strong>hi</strong>" )
msgList . Add ( "hi</b>" , "hi</b>" )
msgList . Add ( "</b>" , "</b>" )
msgList . Add ( "</del>" , "</del>" )
msgList . Add ( "</strong>" , "</strong>" )
msgList . Add ( "<b>" , "<strong></strong>" )
msgList . Add ( "<span style='background-color: yellow;'>hi" , "hi" )
msgList . Add ( "hi</span>" , "hi" )
msgList . Add ( "</span>" , "" )
msgList . Add ( "<span></span>" , "" )
msgList . Add ( "<span ></span>" , "" )
2019-03-27 06:36:14 +00:00
msgList . Add ( "<span><span></span></span>" , "" )
msgList . Add ( "<span><b></b></span>" , "<strong></strong>" )
2019-04-09 05:33:39 +00:00
msgList . Add ( "<h1>t</h1>" , "<h2>t</h2>" )
msgList . Add ( "<h2>t</h2>" , "<h3>t</h3>" )
msgList . Add ( "<h3>t</h3>" , "<h4>t</h4>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "<></>" , "<></>" )
msgList . Add ( "</><>" , "</><>" )
msgList . Add ( "<>" , "<>" )
msgList . Add ( "</>" , "</>" )
2019-03-27 06:36:14 +00:00
msgList . Add ( "<p>hi</p>" , "hi" )
msgList . Add ( "<p></p>" , "" )
msgList . Add ( "<blockquote>hi</blockquote>" , "<blockquote>hi</blockquote>" )
msgList . Add ( "<blockquote><b>hi</b></blockquote>" , "<blockquote><strong>hi</strong></blockquote>" )
msgList . Add ( "<blockquote><meow>hi</meow></blockquote>" , "<blockquote><meow>hi</meow></blockquote>" )
msgList . Add ( "\\<blockquote>hi</blockquote>" , "<blockquote>hi</blockquote>" )
2019-04-08 07:50:10 +00:00
//msgList.Add("\\\\<blockquote><meow>hi</meow></blockquote>", "\\<blockquote><meow>hi</meow></blockquote>") // TODO: Double escapes should print a literal backslash
//msgList.Add("<blockquote>hi</blockquote>", "<blockquote>hi</blockquote>") // TODO: Stop double-entitising this
msgList . Add ( "\\<blockquote>hi</blockquote>\\<blockquote>hi</blockquote>" , "<blockquote>hi</blockquote><blockquote>hi</blockquote>" )
msgList . Add ( "\\<a itemprop=\"author\">Admin</a>" , "<a itemprop="author">Admin</a>" )
msgList . Add ( "<blockquote>\\<a itemprop=\"author\">Admin</a></blockquote>" , "<blockquote><a itemprop="author">Admin</a></blockquote>" )
msgList . Add ( "\n<blockquote>\\<a itemprop=\"author\">Admin</a></blockquote>\n" , "<blockquote><a itemprop="author">Admin</a></blockquote>" )
msgList . Add ( "tt\n<blockquote>\\<a itemprop=\"author\">Admin</a></blockquote>\ntt" , "tt\n<blockquote><a itemprop="author">Admin</a></blockquote>\ntt" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "@" , "@" )
msgList . Add ( "@Admin" , "@1" )
msgList . Add ( "@Bah" , "@Bah" )
msgList . Add ( " @Admin" , "@1" )
msgList . Add ( "\n@Admin" , "@1" )
msgList . Add ( "@Admin\n" , "@1" )
msgList . Add ( "@Admin\ndd" , "@1\ndd" )
msgList . Add ( "d@Admin" , "d@Admin" )
2019-04-08 07:50:10 +00:00
msgList . Add ( "\\@Admin" , "@Admin" )
2019-05-17 08:40:41 +00:00
msgList . Add ( "@元気" , "@元気" )
// TODO: More tests for unicode names?
2019-04-08 07:50:10 +00:00
//msgList.Add("\\\\@Admin", "@1")
2018-11-22 07:21:43 +00:00
//msgList.Add("byte 0", string([]byte{0}), "")
msgList . Add ( "byte 'a'" , string ( [ ] byte { 'a' } ) , "a" )
//msgList.Add("byte 255", string([]byte{255}), "")
//msgList.Add("rune 0", string([]rune{0}), "")
// TODO: Do a test with invalid UTF-8 input
for _ , item := range msgList . Items {
2019-04-19 08:20:10 +00:00
res := c . PreparseMessage ( item . Msg )
2018-11-22 07:21:43 +00:00
if 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 ) {
2019-07-11 07:20:33 +00:00
miscinit ( t )
if ! c . PluginsInited {
c . InitPlugins ( )
}
2018-11-22 07:21:43 +00:00
var msgList = & METriList { nil }
url := "github.com/Azareal/Gosora"
2019-05-22 04:45:07 +00:00
msgList . Add ( "" , "" )
msgList . Add ( "haha" , "haha" )
msgList . Add ( "<b>t</b>" , "<b>t</b>" )
msgList . Add ( "//" , "<red>[Invalid URL]</red>" )
msgList . Add ( "http://" , "<red>[Invalid URL]</red>" )
msgList . Add ( "https://" , "<red>[Invalid URL]</red>" )
msgList . Add ( "ftp://" , "<red>[Invalid URL]</red>" )
msgList . Add ( "git://" , "<red>[Invalid URL]</red>" )
msgList . Add ( "ssh://" , "ssh://" )
msgList . Add ( "// " , "<red>[Invalid URL]</red> " )
msgList . Add ( "// //" , "<red>[Invalid URL]</red> <red>[Invalid URL]</red>" )
msgList . Add ( "http:// " , "<red>[Invalid URL]</red> " )
msgList . Add ( "https:// " , "<red>[Invalid URL]</red> " )
msgList . Add ( "ftp:// " , "<red>[Invalid URL]</red> " )
msgList . Add ( "git:// " , "<red>[Invalid URL]</red> " )
msgList . Add ( "ssh:// " , "ssh:// " )
msgList . Add ( "// t" , "<red>[Invalid URL]</red> t" )
msgList . Add ( "http:// t" , "<red>[Invalid URL]</red> t" )
msgList . Add ( "http:" , "http:" )
msgList . Add ( "https:" , "https:" )
msgList . Add ( "ftp:" , "ftp:" )
msgList . Add ( "git:" , "git:" )
msgList . Add ( "ssh:" , "ssh:" )
msgList . Add ( "http" , "http" )
msgList . Add ( "https" , "https" )
msgList . Add ( "ftp" , "ftp" )
msgList . Add ( "git" , "git" )
msgList . Add ( "ssh" , "ssh" )
msgList . Add ( "ht" , "ht" )
msgList . Add ( "htt" , "htt" )
msgList . Add ( "ft" , "ft" )
msgList . Add ( "gi" , "gi" )
msgList . Add ( "ss" , "ss" )
msgList . Add ( "haha\nhaha\nhaha" , "haha<br>haha<br>haha" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "//" + url , "<a href='//" + url + "'>//" + url + "</a>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "//a" , "<a href='//a'>//a</a>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "https://" + url , "<a href='https://" + url + "'>https://" + url + "</a>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "https://t" , "<a href='https://t'>https://t</a>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "http://" + url , "<a href='http://" + url + "'>http://" + url + "</a>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "#http://" + url , "#http://" + url )
msgList . Add ( "@http://" + url , "<red>[Invalid Profile]</red>ttp://" + url )
2018-11-22 07:21:43 +00:00
msgList . Add ( "//" + url + "\n" , "<a href='//" + url + "'>//" + url + "</a><br>" )
msgList . Add ( "\n//" + url , "<br><a href='//" + url + "'>//" + url + "</a>" )
msgList . Add ( "\n//" + url + "\n" , "<br><a href='//" + url + "'>//" + url + "</a><br>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "\n//" + url + "\n\n" , "<br><a href='//" + url + "'>//" + url + "</a><br><br>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "//" + url + "\n//" + url , "<a href='//" + url + "'>//" + url + "</a><br><a href='//" + url + "'>//" + url + "</a>" )
msgList . Add ( "//" + url + "\n\n//" + url , "<a href='//" + url + "'>//" + url + "</a><br><br><a href='//" + url + "'>//" + url + "</a>" )
2019-04-19 08:20:10 +00:00
msgList . Add ( "//" + c . Site . URL , "<a href='//" + c . Site . URL + "'>//" + c . Site . URL + "</a>" )
msgList . Add ( "//" + c . Site . URL + "\n" , "<a href='//" + c . Site . URL + "'>//" + c . Site . URL + "</a><br>" )
msgList . Add ( "//" + c . Site . URL + "\n//" + c . Site . URL , "<a href='//" + c . Site . URL + "'>//" + c . Site . URL + "</a><br><a href='//" + c . Site . URL + "'>//" + c . Site . URL + "</a>" )
2018-11-22 07:21:43 +00:00
2019-05-23 23:39:24 +00:00
var local = func ( url string ) {
msgList . Add ( "//" + url , "<a href='//" + url + "'>//" + url + "</a>" )
msgList . Add ( "//" + url + "\n" , "<a href='//" + url + "'>//" + url + "</a><br>" )
msgList . Add ( "//" + url + "\n//" + url , "<a href='//" + url + "'>//" + url + "</a><br><a href='//" + url + "'>//" + url + "</a>" )
}
local ( "localhost" )
local ( "127.0.0.1" )
local ( "[::1]" )
msgList . Add ( "https://www.youtube.com/watch?v=lalalalala" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
//msgList.Add("https://www.youtube.com/watch?v=;","<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/;' frameborder=0 allowfullscreen></iframe>")
msgList . Add ( "https://www.youtube.com/watch?v=d;" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/d' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "https://www.youtube.com/watch?v=d;d" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/d' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "https://www.youtube.com/watch?v=alert()" , "<red>[Invalid URL]</red>()" )
msgList . Add ( "https://www.youtube.com/watch?v=js:alert()" , "<red>[Invalid URL]</red>()" )
msgList . Add ( "https://www.youtube.com/watch?v='+><script>alert(\"\")</script><+'" , "<red>[Invalid URL]</red>'+><script>alert(\"\")</script><+'" )
msgList . Add ( "https://www.youtube.com/watch?v='+onready='alert(\"\")'+'" , "<red>[Invalid URL]</red>'+onready='alert(\"\")'+'" )
msgList . Add ( " https://www.youtube.com/watch?v=lalalalala" , " <iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "https://www.youtube.com/watch?v=lalalalala tt" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe> tt" )
msgList . Add ( "https://www.youtube.com/watch?v=lalalalala&d=haha" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "https://gaming.youtube.com/watch?v=lalalalala" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "https://gaming.youtube.com/watch?v=lalalalala&d=haha" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "https://m.youtube.com/watch?v=lalalalala" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "https://m.youtube.com/watch?v=lalalalala&d=haha" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "http://www.youtube.com/watch?v=lalalalala" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
msgList . Add ( "//www.youtube.com/watch?v=lalalalala" , "<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>" )
//msgList.Add("www.youtube.com/watch?v=lalalalala","<iframe class='postIframe' src='https://www.youtube-nocookie.com/embed/lalalalala' frameborder=0 allowfullscreen></iframe>")
2018-11-22 07:21:43 +00:00
msgList . Add ( "#tid-1" , "<a href='/topic/1'>#tid-1</a>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "##tid-1" , "##tid-1" )
msgList . Add ( "# #tid-1" , "# #tid-1" )
msgList . Add ( "@ #tid-1" , "<red>[Invalid Profile]</red>#tid-1" )
msgList . Add ( "@#tid-1" , "<red>[Invalid Profile]</red>tid-1" )
msgList . Add ( "@ #tid-@" , "<red>[Invalid Profile]</red>#tid-@" )
msgList . Add ( "#tid-1 #tid-1" , "<a href='/topic/1'>#tid-1</a> <a href='/topic/1'>#tid-1</a>" )
2019-04-10 07:40:47 +00:00
msgList . Add ( "#tid-0" , "<red>[Invalid Topic]</red>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "https://" + url + "/#tid-1" , "<a href='https://" + url + "/#tid-1'>https://" + url + "/#tid-1</a>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "https://" + url + "/?hi=2" , "<a href='https://" + url + "/?hi=2'>https://" + url + "/?hi=2</a>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "#fid-1" , "<a href='/forum/1'>#fid-1</a>" )
2019-05-23 23:39:24 +00:00
msgList . Add ( " #fid-1" , " <a href='/forum/1'>#fid-1</a>" )
2019-04-10 07:40:47 +00:00
msgList . Add ( "#fid-0" , "<red>[Invalid Forum]</red>" )
2019-05-23 23:39:24 +00:00
msgList . Add ( " #fid-0" , " <red>[Invalid Forum]</red>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "#" , "#" )
msgList . Add ( "# " , "# " )
2019-05-23 23:39:24 +00:00
msgList . Add ( " @" , " @" )
msgList . Add ( " #" , " #" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "#@" , "#@" )
msgList . Add ( "#@ " , "#@ " )
msgList . Add ( "#@1" , "#@1" )
msgList . Add ( "#f" , "#f" )
msgList . Add ( "#ff" , "#ff" )
msgList . Add ( "#ffffid-0" , "#ffffid-0" )
//msgList.Add("#ffffid-0", "#ffffid-0")
msgList . Add ( "#nid-0" , "#nid-0" )
msgList . Add ( "#nnid-0" , "#nnid-0" )
msgList . Add ( "@@" , "<red>[Invalid Profile]</red>" )
msgList . Add ( "@@ @@" , "<red>[Invalid Profile]</red> <red>[Invalid Profile]</red>" )
msgList . Add ( "@@1" , "<red>[Invalid Profile]</red>1" )
msgList . Add ( "@#1" , "<red>[Invalid Profile]</red>1" )
msgList . Add ( "@##1" , "<red>[Invalid Profile]</red>#1" )
msgList . Add ( "@2" , "<red>[Invalid Profile]</red>" )
msgList . Add ( "@2t" , "<red>[Invalid Profile]</red>t" )
msgList . Add ( "@2 t" , "<red>[Invalid Profile]</red> t" )
msgList . Add ( "@2 " , "<red>[Invalid Profile]</red> " )
msgList . Add ( "@2 @2" , "<red>[Invalid Profile]</red> <red>[Invalid Profile]</red>" )
2018-11-22 07:21:43 +00:00
msgList . Add ( "@1" , "<a href='/user/admin.1' class='mention'>@Admin</a>" )
2019-05-23 23:39:24 +00:00
msgList . Add ( " @1" , " <a href='/user/admin.1' class='mention'>@Admin</a>" )
2019-05-22 04:45:07 +00:00
msgList . Add ( "@1t" , "<a href='/user/admin.1' class='mention'>@Admin</a>t" )
msgList . Add ( "@1 " , "<a href='/user/admin.1' class='mention'>@Admin</a> " )
msgList . Add ( "@1 @1" , "<a href='/user/admin.1' class='mention'>@Admin</a> <a href='/user/admin.1' class='mention'>@Admin</a>" )
2019-04-10 07:40:47 +00:00
msgList . Add ( "@0" , "<red>[Invalid Profile]</red>" )
msgList . Add ( "@-1" , "<red>[Invalid Profile]</red>1" )
2018-11-22 07:21:43 +00:00
for _ , item := range msgList . Items {
2019-04-19 08:20:10 +00:00
res := c . ParseMessage ( item . Msg , 1 , "forums" )
2018-11-22 07:21:43 +00:00
if 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 + "'" )
2019-05-22 04:45:07 +00:00
break
}
}
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" )
expect := "<a href='/topic/1'>#nnid-1</a>"
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
2018-11-22 07:21:43 +00:00
}
2019-05-22 04:45:07 +00:00
c . WriteURL ( sb , c . BuildTopicURL ( "" , tid ) , "#longidnameneedtooverflowhack-" + strconv . Itoa ( tid ) )
} )
res = c . ParseMessage ( "#longidnameneedtooverflowhack-1" , 1 , "forums" )
expect = "<a href='/topic/1'>#longidnameneedtooverflowhack-1</a>"
if res != expect {
t . Error ( "Bad output:" , "'" + res + "'" )
t . Error ( "Expected:" , "'" + expect + "'" )
2018-11-22 07:21:43 +00:00
}
}