package feeds import ( "bytes" "testing" "time" ) var atomOutput = ` jmoiron.net blog http://jmoiron.net/blog 2013-01-16T21:52:35-05:00 This work is copyright © Benjamin Button discussion about tech, footie, photos Jason Moiron jmoiron@jmoiron.net Limiting Concurrency in Go 2013-01-16T21:52:35-05:00 tag:jmoiron.net,2013-01-16:/blog/limiting-concurrency-in-go/ <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> A discussion on controlled parallelism in golang Jason Moiron jmoiron@jmoiron.net Logic-less Template Redux 2013-01-16T21:52:35-05:00 tag:jmoiron.net,2013-01-16:/blog/logicless-template-redux/ More thoughts on logicless templates Idiomatic Code Reuse in Go 2013-01-16T21:52:35-05:00 tag:jmoiron.net,2013-01-16:/blog/idiomatic-code-reuse-in-go/ How to use interfaces <em>effectively</em> Never Gonna Give You Up Mp3 2013-01-16T21:52:35-05:00 tag:example.com,2013-01-16:/RickRoll.mp3 Never gonna give you up - Never gonna let you down. String formatting in Go 2013-01-16T21:52:35-05:00 tag:example.com,2013-01-16:/strings How to use things like %s, %v, %d, etc. Go Proverb #1 2013-01-16T21:52:35-05:00 tag:go-proverbs.github.io,2013-01-16:/ Don't communicate by sharing memory, share memory by communicating. ` var rssOutput = ` jmoiron.net blog http://jmoiron.net/blog discussion about tech, footie, photos This work is copyright © Benjamin Button jmoiron@jmoiron.net (Jason Moiron) Wed, 16 Jan 2013 21:52:35 -0500 Limiting Concurrency in Go http://jmoiron.net/blog/limiting-concurrency-in-go/ A discussion on controlled parallelism in golang Go's goroutines make it easy to make embarrassingly parallel programs, but in many "real world" cases resources can be limited and attempting to do everything at once can exhaust your access to them.

]]>
Jason Moiron Wed, 16 Jan 2013 21:52:35 -0500
Logic-less Template Redux http://jmoiron.net/blog/logicless-template-redux/ More thoughts on logicless templates Wed, 16 Jan 2013 21:52:35 -0500 Idiomatic Code Reuse in Go http://jmoiron.net/blog/idiomatic-code-reuse-in-go/ How to use interfaces <em>effectively</em> Wed, 16 Jan 2013 21:52:35 -0500 Never Gonna Give You Up Mp3 http://example.com/RickRoll.mp3 Never gonna give you up - Never gonna let you down. Wed, 16 Jan 2013 21:52:35 -0500 String formatting in Go http://example.com/strings How to use things like %s, %v, %d, etc. Wed, 16 Jan 2013 21:52:35 -0500 Go Proverb #1 https://go-proverbs.github.io/ Wed, 16 Jan 2013 21:52:35 -0500
` var jsonOutput = `{ "version": "https://jsonfeed.org/version/1.1", "title": "jmoiron.net blog", "home_page_url": "http://jmoiron.net/blog", "description": "discussion about tech, footie, photos", "author": { "name": "Jason Moiron" }, "authors": [ { "name": "Jason Moiron" } ], "items": [ { "id": "", "url": "http://jmoiron.net/blog/limiting-concurrency-in-go/", "title": "Limiting Concurrency in Go", "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", "summary": "A discussion on controlled parallelism in golang", "date_published": "2013-01-16T21:52:35-05:00", "author": { "name": "Jason Moiron" }, "authors": [ { "name": "Jason Moiron" } ] }, { "id": "", "url": "http://jmoiron.net/blog/logicless-template-redux/", "title": "Logic-less Template Redux", "summary": "More thoughts on logicless templates", "date_published": "2013-01-16T21:52:35-05:00" }, { "id": "", "url": "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/", "title": "Idiomatic Code Reuse in Go", "summary": "How to use interfaces \u003cem\u003eeffectively\u003c/em\u003e", "image": "http://example.com/cover.jpg", "date_published": "2013-01-16T21:52:35-05:00" }, { "id": "", "url": "http://example.com/RickRoll.mp3", "title": "Never Gonna Give You Up Mp3", "summary": "Never gonna give you up - Never gonna let you down.", "date_published": "2013-01-16T21:52:35-05:00" }, { "id": "", "url": "http://example.com/strings", "title": "String formatting in Go", "summary": "How to use things like %s, %v, %d, etc.", "date_published": "2013-01-16T21:52:35-05:00" }, { "id": "", "url": "https://go-proverbs.github.io/", "title": "Go Proverb #1", "content_html": "Don't communicate by sharing memory, share memory by communicating.", "date_published": "2013-01-16T21:52:35-05:00" } ] }` func TestFeed(t *testing.T) { now, err := time.Parse(time.RFC3339, "2013-01-16T21:52:35-05:00") if err != nil { t.Error(err) } tz := time.FixedZone("EST", -5*60*60) now = now.In(tz) feed := &Feed{ Title: "jmoiron.net blog", Link: &Link{Href: "http://jmoiron.net/blog"}, Description: "discussion about tech, footie, photos", Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, Created: now, Copyright: "This work is copyright © Benjamin Button", } feed.Items = []*Item{ { Title: "Limiting Concurrency in Go", Link: &Link{Href: "http://jmoiron.net/blog/limiting-concurrency-in-go/"}, Description: "A discussion on controlled parallelism in golang", Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, Created: now, Content: `

Go's goroutines make it easy to make embarrassingly parallel programs, but in many "real world" cases resources can be limited and attempting to do everything at once can exhaust your access to them.

`, }, { Title: "Logic-less Template Redux", Link: &Link{Href: "http://jmoiron.net/blog/logicless-template-redux/"}, Description: "More thoughts on logicless templates", Created: now, }, { Title: "Idiomatic Code Reuse in Go", Link: &Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"}, Description: "How to use interfaces effectively", Enclosure: &Enclosure{Url: "http://example.com/cover.jpg", Length: "123456", Type: "image/jpg"}, Created: now, }, { Title: "Never Gonna Give You Up Mp3", Link: &Link{Href: "http://example.com/RickRoll.mp3"}, Enclosure: &Enclosure{Url: "http://example.com/RickRoll.mp3", Length: "123456", Type: "audio/mpeg"}, Description: "Never gonna give you up - Never gonna let you down.", Created: now, }, { Title: "String formatting in Go", Link: &Link{Href: "http://example.com/strings"}, Description: "How to use things like %s, %v, %d, etc.", Created: now, }, { Title: "Go Proverb #1", Link: &Link{Href: "https://go-proverbs.github.io/"}, Content: "Don't communicate by sharing memory, share memory by communicating.", Created: now, }} atom, err := feed.ToAtom() if err != nil { t.Errorf("unexpected error encoding Atom: %v", err) } if atom != atomOutput { t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", atom, atomOutput) } var buf bytes.Buffer if err := feed.WriteAtom(&buf); err != nil { t.Errorf("unexpected error writing Atom: %v", err) } if got := buf.String(); got != atomOutput { t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, atomOutput) } rss, err := feed.ToRss() if err != nil { t.Errorf("unexpected error encoding RSS: %v", err) } if rss != rssOutput { t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", rss, rssOutput) } buf.Reset() if err := feed.WriteRss(&buf); err != nil { t.Errorf("unexpected error writing RSS: %v", err) } if got := buf.String(); got != rssOutput { t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, rssOutput) } json, err := feed.ToJSON() if err != nil { t.Errorf("unexpected error encoding JSON: %v", err) } if json != jsonOutput { t.Errorf("JSON not what was expected. Got:\n%s\n\nExpected:\n%s\n", json, jsonOutput) } buf.Reset() if err := feed.WriteJSON(&buf); err != nil { t.Errorf("unexpected error writing JSON: %v", err) } 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 t.Errorf("JSON not what was expected. Got:\n||%s||\n\nExpected:\n||%s||\n", got, jsonOutput) } } var atomOutputSorted = ` jmoiron.net blog http://jmoiron.net/blog 2013-01-16T21:52:35-05:00 This work is copyright © Benjamin Button discussion about tech, footie, photos Jason Moiron jmoiron@jmoiron.net Limiting Concurrency in Go 2013-01-18T21:52:35-05:00 tag:jmoiron.net,2013-01-18:/blog/limiting-concurrency-in-go/ Logic-less Template Redux 2013-01-17T21:52:35-05:00 tag:jmoiron.net,2013-01-17:/blog/logicless-template-redux/ Idiomatic Code Reuse in Go 2013-01-17T09:52:35-05:00 tag:jmoiron.net,2013-01-17:/blog/idiomatic-code-reuse-in-go/ Never Gonna Give You Up Mp3 2013-01-17T07:52:35-05:00 tag:example.com,2013-01-17:/RickRoll.mp3 String formatting in Go 2013-01-16T21:52:35-05:00 tag:example.com,2013-01-16:/strings ` var rssOutputSorted = ` jmoiron.net blog http://jmoiron.net/blog discussion about tech, footie, photos This work is copyright © Benjamin Button jmoiron@jmoiron.net (Jason Moiron) Wed, 16 Jan 2013 21:52:35 -0500 Limiting Concurrency in Go http://jmoiron.net/blog/limiting-concurrency-in-go/ Fri, 18 Jan 2013 21:52:35 -0500 Logic-less Template Redux http://jmoiron.net/blog/logicless-template-redux/ Thu, 17 Jan 2013 21:52:35 -0500 Idiomatic Code Reuse in Go http://jmoiron.net/blog/idiomatic-code-reuse-in-go/ Thu, 17 Jan 2013 09:52:35 -0500 Never Gonna Give You Up Mp3 http://example.com/RickRoll.mp3 Thu, 17 Jan 2013 07:52:35 -0500 String formatting in Go http://example.com/strings Wed, 16 Jan 2013 21:52:35 -0500 ` var jsonOutputSorted = `{ "version": "https://jsonfeed.org/version/1.1", "title": "jmoiron.net blog", "home_page_url": "http://jmoiron.net/blog", "description": "discussion about tech, footie, photos", "author": { "name": "Jason Moiron" }, "authors": [ { "name": "Jason Moiron" } ], "items": [ { "id": "", "url": "http://jmoiron.net/blog/limiting-concurrency-in-go/", "title": "Limiting Concurrency in Go", "date_published": "2013-01-18T21:52:35-05:00" }, { "id": "", "url": "http://jmoiron.net/blog/logicless-template-redux/", "title": "Logic-less Template Redux", "date_published": "2013-01-17T21:52:35-05:00" }, { "id": "", "url": "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/", "title": "Idiomatic Code Reuse in Go", "date_published": "2013-01-17T09:52:35-05:00" }, { "id": "", "url": "http://example.com/RickRoll.mp3", "title": "Never Gonna Give You Up Mp3", "date_published": "2013-01-17T07:52:35-05:00" }, { "id": "", "url": "http://example.com/strings", "title": "String formatting in Go", "date_published": "2013-01-16T21:52:35-05:00" } ] }` func TestFeedSorted(t *testing.T) { now, err := time.Parse(time.RFC3339, "2013-01-16T21:52:35-05:00") if err != nil { t.Error(err) } tz := time.FixedZone("EST", -5*60*60) now = now.In(tz) feed := &Feed{ Title: "jmoiron.net blog", Link: &Link{Href: "http://jmoiron.net/blog"}, Description: "discussion about tech, footie, photos", Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, Created: now, Copyright: "This work is copyright © Benjamin Button", } feed.Items = []*Item{ { Title: "Limiting Concurrency in Go", Link: &Link{Href: "http://jmoiron.net/blog/limiting-concurrency-in-go/"}, Created: now.Add(time.Duration(time.Hour * 48)), }, { Title: "Logic-less Template Redux", Link: &Link{Href: "http://jmoiron.net/blog/logicless-template-redux/"}, Created: now.Add(time.Duration(time.Hour * 24)), }, { Title: "Idiomatic Code Reuse in Go", Link: &Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"}, Created: now.Add(time.Duration(time.Hour * 12)), }, { Title: "Never Gonna Give You Up Mp3", Link: &Link{Href: "http://example.com/RickRoll.mp3"}, Created: now.Add(time.Duration(time.Hour * 10)), }, { Title: "String formatting in Go", Link: &Link{Href: "http://example.com/strings"}, Created: now, }} feed.Sort(func(a, b *Item) bool { return a.Created.After(b.Created) }) atom, err := feed.ToAtom() if err != nil { t.Errorf("unexpected error encoding Atom: %v", err) } if atom != atomOutputSorted { t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", atom, atomOutputSorted) } var buf bytes.Buffer if err := feed.WriteAtom(&buf); err != nil { t.Errorf("unexpected error writing Atom: %v", err) } if got := buf.String(); got != atomOutputSorted { t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, atomOutputSorted) } rss, err := feed.ToRss() if err != nil { t.Errorf("unexpected error encoding RSS: %v", err) } if rss != rssOutputSorted { t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", rss, rssOutputSorted) } buf.Reset() if err := feed.WriteRss(&buf); err != nil { t.Errorf("unexpected error writing RSS: %v", err) } if got := buf.String(); got != rssOutputSorted { t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, rssOutputSorted) } json, err := feed.ToJSON() if err != nil { t.Errorf("unexpected error encoding JSON: %v", err) } if json != jsonOutputSorted { t.Errorf("JSON not what was expected. Got:\n%s\n\nExpected:\n%s\n", json, jsonOutputSorted) } buf.Reset() if err := feed.WriteJSON(&buf); err != nil { t.Errorf("unexpected error writing JSON: %v", err) } 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 t.Errorf("JSON not what was expected. Got:\n||%s||\n\nExpected:\n||%s||\n", got, jsonOutputSorted) } } func TestFeedNil(t *testing.T) { now, err := time.Parse(time.RFC3339, "2013-01-16T21:52:35-05:00") if err != nil { t.Error(err) } tz := time.FixedZone("EST", -5*60*60) now = now.In(tz) feed := &Feed{ Title: "jmoiron.net blog", Link: nil, Description: "discussion about tech, footie, photos", Author: nil, Created: now, Copyright: "This work is copyright © Benjamin Button", } feed.Items = []*Item{ { Title: "Limiting Concurrency in Go", Link: nil, Description: "A discussion on controlled parallelism in golang", Author: nil, Created: now, Content: `

Go's goroutines make it easy to make embarrassingly parallel programs, but in many "real world" cases resources can be limited and attempting to do everything at once can exhaust your access to them.

`, }} if _, err := feed.ToAtom(); err != nil { t.Errorf("unexpected error encoding Atom: %v", err) } var buf bytes.Buffer if err := feed.WriteAtom(&buf); err != nil { t.Errorf("unexpected error writing Atom: %v", err) } if _, err := feed.ToRss(); err != nil { t.Errorf("unexpected error encoding RSS: %v", err) } buf.Reset() if err := feed.WriteRss(&buf); err != nil { t.Errorf("unexpected error writing RSS: %v", err) } if _, err := feed.ToJSON(); err != nil { t.Errorf("unexpected error encoding JSON: %v", err) } buf.Reset() if err := feed.WriteJSON(&buf); err != nil { t.Errorf("unexpected error writing JSON: %v", err) } } var jsonOutputHub = `{ "version": "https://jsonfeed.org/version/1", "title": "feed title", "hubs": [ { "type": "WebSub", "url": "https://websub-hub.example" } ] }` func TestJSONHub(t *testing.T) { feed := &JSONFeed{ Version: "https://jsonfeed.org/version/1", Title: "feed title", Hubs: []*JSONHub{ { Type: "WebSub", Url: "https://websub-hub.example", }, }, } json, err := feed.ToJSON() if err != nil { t.Errorf("unexpected error encoding JSON: %v", err) } if json != jsonOutputHub { t.Errorf("JSON not what was expected. Got:\n%s\n\nExpected:\n%s\n", json, jsonOutputHub) } }