git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/feeds/feed_test.go (about) 1 package feeds 2 3 import ( 4 "bytes" 5 "testing" 6 "time" 7 ) 8 9 var atomOutput = `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"> 10 <title>jmoiron.net blog</title> 11 <id>http://jmoiron.net/blog</id> 12 <updated>2013-01-16T21:52:35-05:00</updated> 13 <rights>This work is copyright © Benjamin Button</rights> 14 <subtitle>discussion about tech, footie, photos</subtitle> 15 <link href="http://jmoiron.net/blog"></link> 16 <author> 17 <name>Jason Moiron</name> 18 <email>jmoiron@jmoiron.net</email> 19 </author> 20 <entry> 21 <title>Limiting Concurrency in Go</title> 22 <updated>2013-01-16T21:52:35-05:00</updated> 23 <id>tag:jmoiron.net,2013-01-16:/blog/limiting-concurrency-in-go/</id> 24 <content type="html"><p>Go's goroutines make it easy to make <a href="http://collectiveidea.com/blog/archives/2012/12/03/playing-with-go-embarrassingly-parallel-scripts/">embarrassingly parallel programs</a>, but in many &quot;real world&quot; cases resources can be limited and attempting to do everything at once can exhaust your access to them.</p></content> 25 <link href="http://jmoiron.net/blog/limiting-concurrency-in-go/" rel="alternate"></link> 26 <summary type="html">A discussion on controlled parallelism in golang</summary> 27 <author> 28 <name>Jason Moiron</name> 29 <email>jmoiron@jmoiron.net</email> 30 </author> 31 </entry> 32 <entry> 33 <title>Logic-less Template Redux</title> 34 <updated>2013-01-16T21:52:35-05:00</updated> 35 <id>tag:jmoiron.net,2013-01-16:/blog/logicless-template-redux/</id> 36 <link href="http://jmoiron.net/blog/logicless-template-redux/" rel="alternate"></link> 37 <summary type="html">More thoughts on logicless templates</summary> 38 </entry> 39 <entry> 40 <title>Idiomatic Code Reuse in Go</title> 41 <updated>2013-01-16T21:52:35-05:00</updated> 42 <id>tag:jmoiron.net,2013-01-16:/blog/idiomatic-code-reuse-in-go/</id> 43 <link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/" rel="alternate"></link> 44 <link href="http://example.com/cover.jpg" rel="enclosure" type="image/jpg" length="123456"></link> 45 <summary type="html">How to use interfaces <em>effectively</em></summary> 46 </entry> 47 <entry> 48 <title>Never Gonna Give You Up Mp3</title> 49 <updated>2013-01-16T21:52:35-05:00</updated> 50 <id>tag:example.com,2013-01-16:/RickRoll.mp3</id> 51 <link href="http://example.com/RickRoll.mp3" rel="alternate"></link> 52 <link href="http://example.com/RickRoll.mp3" rel="enclosure" type="audio/mpeg" length="123456"></link> 53 <summary type="html">Never gonna give you up - Never gonna let you down.</summary> 54 </entry> 55 <entry> 56 <title>String formatting in Go</title> 57 <updated>2013-01-16T21:52:35-05:00</updated> 58 <id>tag:example.com,2013-01-16:/strings</id> 59 <link href="http://example.com/strings" rel="alternate"></link> 60 <summary type="html">How to use things like %s, %v, %d, etc.</summary> 61 </entry> 62 </feed>` 63 64 var rssOutput = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"> 65 <channel> 66 <title>jmoiron.net blog</title> 67 <link>http://jmoiron.net/blog</link> 68 <description>discussion about tech, footie, photos</description> 69 <copyright>This work is copyright © Benjamin Button</copyright> 70 <managingEditor>jmoiron@jmoiron.net (Jason Moiron)</managingEditor> 71 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 72 <item> 73 <title>Limiting Concurrency in Go</title> 74 <link>http://jmoiron.net/blog/limiting-concurrency-in-go/</link> 75 <description>A discussion on controlled parallelism in golang</description> 76 <content:encoded><![CDATA[<p>Go's goroutines make it easy to make <a href="http://collectiveidea.com/blog/archives/2012/12/03/playing-with-go-embarrassingly-parallel-scripts/">embarrassingly parallel programs</a>, but in many "real world" cases resources can be limited and attempting to do everything at once can exhaust your access to them.</p>]]></content:encoded> 77 <author>Jason Moiron</author> 78 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 79 </item> 80 <item> 81 <title>Logic-less Template Redux</title> 82 <link>http://jmoiron.net/blog/logicless-template-redux/</link> 83 <description>More thoughts on logicless templates</description> 84 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 85 </item> 86 <item> 87 <title>Idiomatic Code Reuse in Go</title> 88 <link>http://jmoiron.net/blog/idiomatic-code-reuse-in-go/</link> 89 <description>How to use interfaces <em>effectively</em></description> 90 <enclosure url="http://example.com/cover.jpg" length="123456" type="image/jpg"></enclosure> 91 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 92 </item> 93 <item> 94 <title>Never Gonna Give You Up Mp3</title> 95 <link>http://example.com/RickRoll.mp3</link> 96 <description>Never gonna give you up - Never gonna let you down.</description> 97 <enclosure url="http://example.com/RickRoll.mp3" length="123456" type="audio/mpeg"></enclosure> 98 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 99 </item> 100 <item> 101 <title>String formatting in Go</title> 102 <link>http://example.com/strings</link> 103 <description>How to use things like %s, %v, %d, etc.</description> 104 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 105 </item> 106 </channel> 107 </rss>` 108 109 var jsonOutput = `{ 110 "version": "https://jsonfeed.org/version/1.1", 111 "title": "jmoiron.net blog", 112 "home_page_url": "http://jmoiron.net/blog", 113 "description": "discussion about tech, footie, photos", 114 "author": { 115 "name": "Jason Moiron" 116 }, 117 "authors": [ 118 { 119 "name": "Jason Moiron" 120 } 121 ], 122 "items": [ 123 { 124 "id": "", 125 "url": "http://jmoiron.net/blog/limiting-concurrency-in-go/", 126 "title": "Limiting Concurrency in Go", 127 "content_html": "\u003cp\u003eGo's goroutines make it easy to make \u003ca href=\"http://collectiveidea.com/blog/archives/2012/12/03/playing-with-go-embarrassingly-parallel-scripts/\"\u003eembarrassingly parallel programs\u003c/a\u003e, but in many \u0026quot;real world\u0026quot; cases resources can be limited and attempting to do everything at once can exhaust your access to them.\u003c/p\u003e", 128 "summary": "A discussion on controlled parallelism in golang", 129 "date_published": "2013-01-16T21:52:35-05:00", 130 "author": { 131 "name": "Jason Moiron" 132 }, 133 "authors": [ 134 { 135 "name": "Jason Moiron" 136 } 137 ] 138 }, 139 { 140 "id": "", 141 "url": "http://jmoiron.net/blog/logicless-template-redux/", 142 "title": "Logic-less Template Redux", 143 "summary": "More thoughts on logicless templates", 144 "date_published": "2013-01-16T21:52:35-05:00" 145 }, 146 { 147 "id": "", 148 "url": "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/", 149 "title": "Idiomatic Code Reuse in Go", 150 "summary": "How to use interfaces \u003cem\u003eeffectively\u003c/em\u003e", 151 "image": "http://example.com/cover.jpg", 152 "date_published": "2013-01-16T21:52:35-05:00" 153 }, 154 { 155 "id": "", 156 "url": "http://example.com/RickRoll.mp3", 157 "title": "Never Gonna Give You Up Mp3", 158 "summary": "Never gonna give you up - Never gonna let you down.", 159 "date_published": "2013-01-16T21:52:35-05:00", 160 "attachments": [ 161 { 162 "url": "http://example.com/RickRoll.mp3", 163 "mime_type": "audio/mpeg", 164 "size_in_bytes": 123456 165 } 166 ] 167 }, 168 { 169 "id": "", 170 "url": "http://example.com/strings", 171 "title": "String formatting in Go", 172 "summary": "How to use things like %s, %v, %d, etc.", 173 "date_published": "2013-01-16T21:52:35-05:00" 174 } 175 ] 176 }` 177 178 func TestFeed(t *testing.T) { 179 now, err := time.Parse(time.RFC3339, "2013-01-16T21:52:35-05:00") 180 if err != nil { 181 t.Error(err) 182 } 183 tz := time.FixedZone("EST", -5*60*60) 184 now = now.In(tz) 185 186 feed := &Feed{ 187 Title: "jmoiron.net blog", 188 Link: &Link{Href: "http://jmoiron.net/blog"}, 189 Description: "discussion about tech, footie, photos", 190 Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, 191 Created: now, 192 Copyright: "This work is copyright © Benjamin Button", 193 } 194 195 feed.Items = []*Item{ 196 { 197 Title: "Limiting Concurrency in Go", 198 Link: &Link{Href: "http://jmoiron.net/blog/limiting-concurrency-in-go/"}, 199 Description: "A discussion on controlled parallelism in golang", 200 Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, 201 Created: now, 202 Content: `<p>Go's goroutines make it easy to make <a href="http://collectiveidea.com/blog/archives/2012/12/03/playing-with-go-embarrassingly-parallel-scripts/">embarrassingly parallel programs</a>, but in many "real world" cases resources can be limited and attempting to do everything at once can exhaust your access to them.</p>`, 203 }, 204 { 205 Title: "Logic-less Template Redux", 206 Link: &Link{Href: "http://jmoiron.net/blog/logicless-template-redux/"}, 207 Description: "More thoughts on logicless templates", 208 Created: now, 209 }, 210 { 211 Title: "Idiomatic Code Reuse in Go", 212 Link: &Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"}, 213 Description: "How to use interfaces <em>effectively</em>", 214 Enclosure: &Enclosure{Url: "http://example.com/cover.jpg", Length: "123456", Type: "image/jpg"}, 215 Created: now, 216 }, 217 { 218 Title: "Never Gonna Give You Up Mp3", 219 Link: &Link{Href: "http://example.com/RickRoll.mp3"}, 220 Enclosure: &Enclosure{Url: "http://example.com/RickRoll.mp3", Length: "123456", Type: "audio/mpeg"}, 221 Description: "Never gonna give you up - Never gonna let you down.", 222 Created: now, 223 }, 224 { 225 Title: "String formatting in Go", 226 Link: &Link{Href: "http://example.com/strings"}, 227 Description: "How to use things like %s, %v, %d, etc.", 228 Created: now, 229 }} 230 231 atom, err := feed.ToAtom() 232 if err != nil { 233 t.Errorf("unexpected error encoding Atom: %v", err) 234 } 235 if atom != atomOutput { 236 t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", atom, atomOutput) 237 } 238 var buf bytes.Buffer 239 if err := feed.WriteAtom(&buf); err != nil { 240 t.Errorf("unexpected error writing Atom: %v", err) 241 } 242 if got := buf.String(); got != atomOutput { 243 t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, atomOutput) 244 } 245 246 rss, err := feed.ToRss() 247 if err != nil { 248 t.Errorf("unexpected error encoding RSS: %v", err) 249 } 250 if rss != rssOutput { 251 t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", rss, rssOutput) 252 } 253 buf.Reset() 254 if err := feed.WriteRss(&buf); err != nil { 255 t.Errorf("unexpected error writing RSS: %v", err) 256 } 257 if got := buf.String(); got != rssOutput { 258 t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, rssOutput) 259 } 260 261 json, err := feed.ToJSON() 262 if err != nil { 263 t.Errorf("unexpected error encoding JSON: %v", err) 264 } 265 if json != jsonOutput { 266 t.Errorf("JSON not what was expected. Got:\n%s\n\nExpected:\n%s\n", json, jsonOutput) 267 } 268 buf.Reset() 269 if err := feed.WriteJSON(&buf); err != nil { 270 t.Errorf("unexpected error writing JSON: %v", err) 271 } 272 if got := buf.String(); got != jsonOutput+"\n" { //json.Encode appends a newline after the JSON output: https://github.com/golang/go/commit/6f25f1d4c901417af1da65e41992d71c30f64f8f#diff-50848cbd686f250623a2ef6ddb07e157 273 t.Errorf("JSON not what was expected. Got:\n||%s||\n\nExpected:\n||%s||\n", got, jsonOutput) 274 } 275 } 276 277 var atomOutputSorted = `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"> 278 <title>jmoiron.net blog</title> 279 <id>http://jmoiron.net/blog</id> 280 <updated>2013-01-16T21:52:35-05:00</updated> 281 <rights>This work is copyright © Benjamin Button</rights> 282 <subtitle>discussion about tech, footie, photos</subtitle> 283 <link href="http://jmoiron.net/blog"></link> 284 <author> 285 <name>Jason Moiron</name> 286 <email>jmoiron@jmoiron.net</email> 287 </author> 288 <entry> 289 <title>Limiting Concurrency in Go</title> 290 <updated>2013-01-18T21:52:35-05:00</updated> 291 <id>tag:jmoiron.net,2013-01-18:/blog/limiting-concurrency-in-go/</id> 292 <link href="http://jmoiron.net/blog/limiting-concurrency-in-go/" rel="alternate"></link> 293 <summary type="html"></summary> 294 </entry> 295 <entry> 296 <title>Logic-less Template Redux</title> 297 <updated>2013-01-17T21:52:35-05:00</updated> 298 <id>tag:jmoiron.net,2013-01-17:/blog/logicless-template-redux/</id> 299 <link href="http://jmoiron.net/blog/logicless-template-redux/" rel="alternate"></link> 300 <summary type="html"></summary> 301 </entry> 302 <entry> 303 <title>Idiomatic Code Reuse in Go</title> 304 <updated>2013-01-17T09:52:35-05:00</updated> 305 <id>tag:jmoiron.net,2013-01-17:/blog/idiomatic-code-reuse-in-go/</id> 306 <link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/" rel="alternate"></link> 307 <summary type="html"></summary> 308 </entry> 309 <entry> 310 <title>Never Gonna Give You Up Mp3</title> 311 <updated>2013-01-17T07:52:35-05:00</updated> 312 <id>tag:example.com,2013-01-17:/RickRoll.mp3</id> 313 <link href="http://example.com/RickRoll.mp3" rel="alternate"></link> 314 <summary type="html"></summary> 315 </entry> 316 <entry> 317 <title>String formatting in Go</title> 318 <updated>2013-01-16T21:52:35-05:00</updated> 319 <id>tag:example.com,2013-01-16:/strings</id> 320 <link href="http://example.com/strings" rel="alternate"></link> 321 <summary type="html"></summary> 322 </entry> 323 </feed>` 324 325 var rssOutputSorted = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"> 326 <channel> 327 <title>jmoiron.net blog</title> 328 <link>http://jmoiron.net/blog</link> 329 <description>discussion about tech, footie, photos</description> 330 <copyright>This work is copyright © Benjamin Button</copyright> 331 <managingEditor>jmoiron@jmoiron.net (Jason Moiron)</managingEditor> 332 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 333 <item> 334 <title>Limiting Concurrency in Go</title> 335 <link>http://jmoiron.net/blog/limiting-concurrency-in-go/</link> 336 <description></description> 337 <pubDate>Fri, 18 Jan 2013 21:52:35 -0500</pubDate> 338 </item> 339 <item> 340 <title>Logic-less Template Redux</title> 341 <link>http://jmoiron.net/blog/logicless-template-redux/</link> 342 <description></description> 343 <pubDate>Thu, 17 Jan 2013 21:52:35 -0500</pubDate> 344 </item> 345 <item> 346 <title>Idiomatic Code Reuse in Go</title> 347 <link>http://jmoiron.net/blog/idiomatic-code-reuse-in-go/</link> 348 <description></description> 349 <pubDate>Thu, 17 Jan 2013 09:52:35 -0500</pubDate> 350 </item> 351 <item> 352 <title>Never Gonna Give You Up Mp3</title> 353 <link>http://example.com/RickRoll.mp3</link> 354 <description></description> 355 <pubDate>Thu, 17 Jan 2013 07:52:35 -0500</pubDate> 356 </item> 357 <item> 358 <title>String formatting in Go</title> 359 <link>http://example.com/strings</link> 360 <description></description> 361 <pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate> 362 </item> 363 </channel> 364 </rss>` 365 366 var jsonOutputSorted = `{ 367 "version": "https://jsonfeed.org/version/1.1", 368 "title": "jmoiron.net blog", 369 "home_page_url": "http://jmoiron.net/blog", 370 "description": "discussion about tech, footie, photos", 371 "author": { 372 "name": "Jason Moiron" 373 }, 374 "authors": [ 375 { 376 "name": "Jason Moiron" 377 } 378 ], 379 "items": [ 380 { 381 "id": "", 382 "url": "http://jmoiron.net/blog/limiting-concurrency-in-go/", 383 "title": "Limiting Concurrency in Go", 384 "date_published": "2013-01-18T21:52:35-05:00" 385 }, 386 { 387 "id": "", 388 "url": "http://jmoiron.net/blog/logicless-template-redux/", 389 "title": "Logic-less Template Redux", 390 "date_published": "2013-01-17T21:52:35-05:00" 391 }, 392 { 393 "id": "", 394 "url": "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/", 395 "title": "Idiomatic Code Reuse in Go", 396 "date_published": "2013-01-17T09:52:35-05:00" 397 }, 398 { 399 "id": "", 400 "url": "http://example.com/RickRoll.mp3", 401 "title": "Never Gonna Give You Up Mp3", 402 "date_published": "2013-01-17T07:52:35-05:00" 403 }, 404 { 405 "id": "", 406 "url": "http://example.com/strings", 407 "title": "String formatting in Go", 408 "date_published": "2013-01-16T21:52:35-05:00" 409 } 410 ] 411 }` 412 413 func TestFeedSorted(t *testing.T) { 414 now, err := time.Parse(time.RFC3339, "2013-01-16T21:52:35-05:00") 415 if err != nil { 416 t.Error(err) 417 } 418 tz := time.FixedZone("EST", -5*60*60) 419 now = now.In(tz) 420 421 feed := &Feed{ 422 Title: "jmoiron.net blog", 423 Link: &Link{Href: "http://jmoiron.net/blog"}, 424 Description: "discussion about tech, footie, photos", 425 Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, 426 Created: now, 427 Copyright: "This work is copyright © Benjamin Button", 428 } 429 430 feed.Items = []*Item{ 431 { 432 Title: "Limiting Concurrency in Go", 433 Link: &Link{Href: "http://jmoiron.net/blog/limiting-concurrency-in-go/"}, 434 Created: now.Add(time.Duration(time.Hour * 48)), 435 }, 436 { 437 Title: "Logic-less Template Redux", 438 Link: &Link{Href: "http://jmoiron.net/blog/logicless-template-redux/"}, 439 Created: now.Add(time.Duration(time.Hour * 24)), 440 }, 441 { 442 Title: "Idiomatic Code Reuse in Go", 443 Link: &Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"}, 444 Created: now.Add(time.Duration(time.Hour * 12)), 445 }, 446 { 447 Title: "Never Gonna Give You Up Mp3", 448 Link: &Link{Href: "http://example.com/RickRoll.mp3"}, 449 Created: now.Add(time.Duration(time.Hour * 10)), 450 }, 451 { 452 Title: "String formatting in Go", 453 Link: &Link{Href: "http://example.com/strings"}, 454 Created: now, 455 }} 456 457 feed.Sort(func(a, b *Item) bool { 458 return a.Created.After(b.Created) 459 }) 460 atom, err := feed.ToAtom() 461 if err != nil { 462 t.Errorf("unexpected error encoding Atom: %v", err) 463 } 464 if atom != atomOutputSorted { 465 t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", atom, atomOutputSorted) 466 } 467 var buf bytes.Buffer 468 if err := feed.WriteAtom(&buf); err != nil { 469 t.Errorf("unexpected error writing Atom: %v", err) 470 } 471 if got := buf.String(); got != atomOutputSorted { 472 t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, atomOutputSorted) 473 } 474 475 rss, err := feed.ToRss() 476 if err != nil { 477 t.Errorf("unexpected error encoding RSS: %v", err) 478 } 479 480 if rss != rssOutputSorted { 481 t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", rss, rssOutputSorted) 482 } 483 buf.Reset() 484 if err := feed.WriteRss(&buf); err != nil { 485 t.Errorf("unexpected error writing RSS: %v", err) 486 } 487 if got := buf.String(); got != rssOutputSorted { 488 t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, rssOutputSorted) 489 } 490 491 json, err := feed.ToJSON() 492 if err != nil { 493 t.Errorf("unexpected error encoding JSON: %v", err) 494 } 495 if json != jsonOutputSorted { 496 t.Errorf("JSON not what was expected. Got:\n%s\n\nExpected:\n%s\n", json, jsonOutputSorted) 497 } 498 buf.Reset() 499 if err := feed.WriteJSON(&buf); err != nil { 500 t.Errorf("unexpected error writing JSON: %v", err) 501 } 502 if got := buf.String(); got != jsonOutputSorted+"\n" { //json.Encode appends a newline after the JSON output: https://github.com/golang/go/commit/6f25f1d4c901417af1da65e41992d71c30f64f8f#diff-50848cbd686f250623a2ef6ddb07e157 503 t.Errorf("JSON not what was expected. Got:\n||%s||\n\nExpected:\n||%s||\n", got, jsonOutputSorted) 504 } 505 } 506 507 var jsonOutputHub = `{ 508 "version": "https://jsonfeed.org/version/1.1", 509 "title": "feed title", 510 "hubs": [ 511 { 512 "type": "WebSub", 513 "url": "https://websub-hub.example" 514 } 515 ] 516 }` 517 518 func TestJSONHub(t *testing.T) { 519 feed := &JSONFeed{ 520 Version: "https://jsonfeed.org/version/1.1", 521 Title: "feed title", 522 Hubs: []*JSONHub{ 523 { 524 Type: "WebSub", 525 Url: "https://websub-hub.example", 526 }, 527 }, 528 } 529 json, err := feed.ToJSON() 530 if err != nil { 531 t.Errorf("unexpected error encoding JSON: %v", err) 532 } 533 if json != jsonOutputHub { 534 t.Errorf("JSON not what was expected. Got:\n%s\n\nExpected:\n%s\n", json, jsonOutputHub) 535 } 536 }