Add go-fuzz to all exportable Funcs (#31)
* Initial Fuzzing Logic * Add more fuzzing, add gitignore, add cleanup, gomod updates * Exclude fuzz directories from commits * Update docs on Fuzzing * Update docs with Examples and Offline Mode * Remove duplicate line in Makefile
This commit is contained in:
parent
8139fb1eaf
commit
975adb8ec2
|
@ -3,7 +3,7 @@ name: go-cicd
|
|||
|
||||
jobs:
|
||||
|
||||
golangci-lint:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
|
@ -16,10 +16,10 @@ jobs:
|
|||
echo "::set-env name=GOPATH::${{ github.workspace }}/go"
|
||||
echo "::add-path::${{ github.workspace }}/go/bin"
|
||||
- name: checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
path: podcast/go/src/github.com/${{ github.repository }}
|
||||
path: go/src/github.com/${{ github.repository }}
|
||||
- name: Install golangci-lint
|
||||
shell: bash
|
||||
run: |
|
||||
|
@ -27,9 +27,10 @@ jobs:
|
|||
- name: Run linters
|
||||
shell: bash
|
||||
run: |
|
||||
cd $GOPATH/src/github.com/${{ github.repository }}
|
||||
golangci-lint -E bodyclose,misspell,gocyclo,dupl,gofmt,golint,unconvert,depguard,interfacer run
|
||||
|
||||
coveralls:
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
|
@ -62,7 +63,9 @@ jobs:
|
|||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: coverage.lcov
|
||||
|
||||
go-bench:
|
||||
benchmark:
|
||||
# TODO: actually compare to previous runs
|
||||
# maybe this setup: https://github.com/knqyf263/cob
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
|
@ -75,13 +78,14 @@ jobs:
|
|||
echo "::set-env name=GOPATH::${{ github.workspace }}/go"
|
||||
echo "::add-path::${{ github.workspace }}/go/bin"
|
||||
- name: checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
path: podcast/go/src/github.com/${{ github.repository }}
|
||||
path: go/src/github.com/${{ github.repository }}
|
||||
- name: Run Benchmark
|
||||
shell: bash
|
||||
run: |
|
||||
cd $GOPATH/src/github.com/${{ github.repository }}
|
||||
go test -test.run Benchmark -cpu 1 -bench .
|
||||
|
||||
go-test:
|
||||
|
@ -102,10 +106,12 @@ jobs:
|
|||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
path: podcast/go/src/github.com/${{ github.repository }}
|
||||
path: go/src/github.com/${{ github.repository }}
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
cd $GOPATH/src/github.com/${{ github.repository }}
|
||||
go test -v -covermode=count
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
profile.out
|
||||
README.md.tmp
|
||||
|
||||
corpus
|
||||
crashers
|
||||
suppressions
|
||||
workdir
|
||||
podcast-fuzz.zip
|
||||
|
|
6
Makefile
6
Makefile
|
@ -3,13 +3,15 @@ SHELL = /bin/bash
|
|||
GITHUB_REPO:=eduncan911/podcast
|
||||
|
||||
README:
|
||||
godoc2ghmd github.com/$(GITHUB_REPO) > README.md.tmp
|
||||
godoc2ghmd -play -ex -verify_import_links=0 github.com/$(GITHUB_REPO) > README.md.tmp
|
||||
echo "[![GoDoc](https://godoc.org/github.com/$(GITHUB_REPO)?status.svg)](https://godoc.org/github.com/$(GITHUB_REPO))" > README.md
|
||||
echo "[![Build Status](https://github.com/$(GITHUB_REPO)/workflows/go-cicd/badge.svg)](https://github.com/$(GITHUB_REPO)/actions?workflow=go-cicd)" >> README.md
|
||||
echo "[![Coverage Status](https://coveralls.io/repos/github/$(GITHUB_REPO)/badge.svg?branch=master)](https://coveralls.io/github/$(GITHUB_REPO)?branch=master)" >> README.md
|
||||
echo "[![Go Report Card](https://goreportcard.com/badge/github.com/$(GITHUB_REPO))](https://goreportcard.com/report/github.com/$(GITHUB_REPO))" >> README.md
|
||||
echo "[![GoDoc](https://godoc.org/github.com/$(GITHUB_REPO)?status.svg)](https://godoc.org/github.com/$(GITHUB_REPO))"
|
||||
echo "[![MIT License](https://img.shields.io/npm/l/mediaelement.svg)](https://eduncan911.mit-license.org/)" >> README.md
|
||||
echo >>README.md
|
||||
cat README.md.tmp >> README.md
|
||||
rm README.md.tmp
|
||||
|
||||
clean:
|
||||
rm -rf corpus crashers suppressions workdir podcast-fuzz.zip
|
||||
|
|
602
README.md
602
README.md
|
@ -37,16 +37,42 @@ new installs, tested with Go 1.13. To keep 1.7 compatibility, we use
|
|||
If either runtime has an issue, please create an Issue and I will address.
|
||||
|
||||
### Extensibility
|
||||
In no way are you restricted in having full control over your feeds. You may
|
||||
choose to skip the API methods and instead use the structs directly. The
|
||||
fields have been grouped by RSS 2.0 and iTunes fields.
|
||||
For version 1.x, you are not restricted in having full control over your feeds.
|
||||
You may choose to skip the API methods and instead use the structs directly. The
|
||||
fields have been grouped by RSS 2.0 and iTunes fields with iTunes specific fields
|
||||
all prefixed with the letter `I`.
|
||||
|
||||
iTunes specific fields are all prefixed with the letter `I`.
|
||||
However, do note that the 2.x version currently in progress will break this
|
||||
extensibility and enforce API methods going forward. This is to ensure that the feed
|
||||
can both be marshalled, and unmarshalled back and forth (current 1.x branch can only
|
||||
be unmarshalled - hence the work for 2.x).
|
||||
|
||||
### References
|
||||
RSS 2.0: <a href="https://cyber.harvard.edu/rss/rss.html">https://cyber.harvard.edu/rss/rss.html</a>
|
||||
### Fuzzing Inputs
|
||||
`go-fuzz` has been added in 1.4.1, covering all exported API methods. They have been
|
||||
ran extensively and no issues have come out of them yet (most tests were ran overnight,
|
||||
over about 11 hours with zero crashes).
|
||||
|
||||
Podcasts: <a href="https://help.apple.com/itc/podcasts_connect/#/itca5b22233">https://help.apple.com/itc/podcasts_connect/#/itca5b22233</a>
|
||||
If you wish to help fuzz the inputs, with Go 1.13 or later you can run `go-fuzz` on any
|
||||
of the inputs.
|
||||
|
||||
go get -u github.com/dvyukov/go-fuzz/go-fuzz
|
||||
go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
go get -u github.com/eduncan911/podcast
|
||||
cd $GOPATH/src/github.com/eduncan911/podcast
|
||||
go-fuzz-build
|
||||
go-fuzz -func FuzzPodcastAddItem
|
||||
|
||||
To obtain a list of available funcs to pass, just run `go-fuzz` without any parameters:
|
||||
|
||||
$ go-fuzz
|
||||
2020/02/13 07:27:32 -func flag not provided, but multiple fuzz functions available:
|
||||
FuzzItemAddDuration, FuzzItemAddEnclosure, FuzzItemAddImage, FuzzItemAddPubDate,
|
||||
FuzzItemAddSummary, FuzzPodcastAddAtomLink, FuzzPodcastAddAuthor, FuzzPodcastAddCategory,
|
||||
FuzzPodcastAddImage, FuzzPodcastAddItem, FuzzPodcastAddLastBuildDate, FuzzPodcastAddPubDate,
|
||||
FuzzPodcastAddSubTitle, FuzzPodcastAddSummary, FuzzPodcastBytes, FuzzPodcastEncode,
|
||||
FuzzPodcastNew
|
||||
|
||||
If you do find an issue, please raise an issue immediately and I will quickly address.
|
||||
|
||||
### Roadmap
|
||||
The 1.x branch is now mostly in maintenance mode, open to PRs. This means no
|
||||
|
@ -70,6 +96,13 @@ However, the new 2.x branch, while keeping the same API, is expected break those
|
|||
bypass the API methods and use the underlying public properties instead.
|
||||
|
||||
### Release Notes
|
||||
1.4.1
|
||||
|
||||
* Implement fuzz logic testing of exported funcs (#31)
|
||||
* Upgrade CICD Pipeline Tooling (#31)
|
||||
* Update documentation for 1.x and 2.3 (#31)
|
||||
* Allow godoc2ghmd to run without network (#31)
|
||||
|
||||
1.4.0
|
||||
|
||||
* Add Go Modules, Update vendor folder (#26, #25)
|
||||
|
@ -121,6 +154,226 @@ bypass the API methods and use the underlying public properties instead.
|
|||
* Initial release.
|
||||
* Full documentation, full examples and complete code coverage.
|
||||
|
||||
### References
|
||||
RSS 2.0: <a href="https://cyber.harvard.edu/rss/rss.html">https://cyber.harvard.edu/rss/rss.html</a>
|
||||
|
||||
Podcasts: <a href="https://help.apple.com/itc/podcasts_connect/#/itca5b22233">https://help.apple.com/itc/podcasts_connect/#/itca5b22233</a>
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
// ResponseWriter example using Podcast.Encode(w io.Writer).
|
||||
//
|
||||
httpHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// instantiate a new Podcast
|
||||
p := podcast.New(
|
||||
"eduncan911 Podcasts",
|
||||
"http://eduncan911.com/",
|
||||
"An example Podcast",
|
||||
&pubDate, &updatedDate,
|
||||
)
|
||||
|
||||
// add some channel properties
|
||||
p.AddAuthor("Jane Doe", "me@janedoe.com")
|
||||
p.AddAtomLink("http://eduncan911.com/feed.rss")
|
||||
p.AddImage("http://janedoe.com/i.jpg")
|
||||
p.AddSummary(`link <a href="http://example.com">example.com</a>`)
|
||||
p.IExplicit = "no"
|
||||
|
||||
for i := int64(1); i < 3; i++ {
|
||||
n := strconv.FormatInt(i, 10)
|
||||
d := pubDate.AddDate(0, 0, int(i))
|
||||
|
||||
// create an Item
|
||||
item := podcast.Item{
|
||||
Title: "Episode " + n,
|
||||
Link: "http://example.com/" + n + ".mp3",
|
||||
Description: "Description for Episode " + n,
|
||||
PubDate: &d,
|
||||
}
|
||||
item.AddImage("http://example.com/episode-" + n + ".png")
|
||||
item.AddSummary(`item <a href="http://example.com">example.com</a>`)
|
||||
// add a Download to the Item
|
||||
item.AddEnclosure("http://e.com/"+n+".mp3", podcast.MP3, 55*(i+1))
|
||||
|
||||
// add the Item and check for validation errors
|
||||
if _, err := p.AddItem(item); err != nil {
|
||||
fmt.Println(item.Title, ": error", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// set the Content Type to that of XML
|
||||
w.Header().Set("Content-Type", "application/xml")
|
||||
|
||||
// finally, Encode and write the Podcast to the ResponseWriter.
|
||||
//
|
||||
// a simple pattern is to handle any errors within this check.
|
||||
// alternatively if using middleware, you can just return
|
||||
// the Podcast entity as it also implements the io.Writer interface
|
||||
// that complies with several middleware packages.
|
||||
if err := p.Encode(w); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
httpHandler(rr, nil)
|
||||
os.Stdout.Write(rr.Body.Bytes())
|
||||
// Output:
|
||||
// <?xml version="1.0" encoding="UTF-8"?>
|
||||
// <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
|
||||
// <channel>
|
||||
// <title>eduncan911 Podcasts</title>
|
||||
// <link>http://eduncan911.com/</link>
|
||||
// <description>An example Podcast</description>
|
||||
// <generator>go podcast v1.3.1 (github.com/eduncan911/podcast)</generator>
|
||||
// <language>en-us</language>
|
||||
// <lastBuildDate>Mon, 06 Feb 2017 08:21:52 +0000</lastBuildDate>
|
||||
// <managingEditor>me@janedoe.com (Jane Doe)</managingEditor>
|
||||
// <pubDate>Sat, 04 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <image>
|
||||
// <url>http://janedoe.com/i.jpg</url>
|
||||
// <title>eduncan911 Podcasts</title>
|
||||
// <link>http://eduncan911.com/</link>
|
||||
// </image>
|
||||
// <atom:link href="http://eduncan911.com/feed.rss" rel="self" type="application/rss+xml"></atom:link>
|
||||
// <itunes:author>me@janedoe.com (Jane Doe)</itunes:author>
|
||||
// <itunes:summary><![CDATA[link <a href="http://example.com">example.com</a>]]></itunes:summary>
|
||||
// <itunes:image href="http://janedoe.com/i.jpg"></itunes:image>
|
||||
// <itunes:explicit>no</itunes:explicit>
|
||||
// <item>
|
||||
// <guid>http://e.com/1.mp3</guid>
|
||||
// <title>Episode 1</title>
|
||||
// <link>http://example.com/1.mp3</link>
|
||||
// <description>Description for Episode 1</description>
|
||||
// <pubDate>Sun, 05 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <enclosure url="http://e.com/1.mp3" length="110" type="audio/mpeg"></enclosure>
|
||||
// <itunes:author>me@janedoe.com (Jane Doe)</itunes:author>
|
||||
// <itunes:summary><![CDATA[item <a href="http://example.com">example.com</a>]]></itunes:summary>
|
||||
// <itunes:image href="http://example.com/episode-1.png"></itunes:image>
|
||||
// </item>
|
||||
// <item>
|
||||
// <guid>http://e.com/2.mp3</guid>
|
||||
// <title>Episode 2</title>
|
||||
// <link>http://example.com/2.mp3</link>
|
||||
// <description>Description for Episode 2</description>
|
||||
// <pubDate>Mon, 06 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <enclosure url="http://e.com/2.mp3" length="165" type="audio/mpeg"></enclosure>
|
||||
// <itunes:author>me@janedoe.com (Jane Doe)</itunes:author>
|
||||
// <itunes:summary><![CDATA[item <a href="http://example.com">example.com</a>]]></itunes:summary>
|
||||
// <itunes:image href="http://example.com/episode-2.png"></itunes:image>
|
||||
// </item>
|
||||
// </channel>
|
||||
// </rss>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
// instantiate a new Podcast
|
||||
p := podcast.New(
|
||||
"Sample Podcasts",
|
||||
"http://example.com/",
|
||||
"An example Podcast",
|
||||
&createdDate, &updatedDate,
|
||||
)
|
||||
|
||||
// add some channel properties
|
||||
p.ISubtitle = "A simple Podcast"
|
||||
p.AddSummary(`link <a href="http://example.com">example.com</a>`)
|
||||
p.AddImage("http://example.com/podcast.jpg")
|
||||
p.AddAuthor("Jane Doe", "jane.doe@example.com")
|
||||
p.AddAtomLink("http://example.com/atom.rss")
|
||||
|
||||
for i := int64(9); i < 11; i++ {
|
||||
n := strconv.FormatInt(i, 10)
|
||||
d := pubDate.AddDate(0, 0, int(i))
|
||||
|
||||
// create an Item
|
||||
item := podcast.Item{
|
||||
Title: "Episode " + n,
|
||||
Description: "Description for Episode " + n,
|
||||
ISubtitle: "A simple episode " + n,
|
||||
PubDate: &d,
|
||||
}
|
||||
item.AddImage("http://example.com/episode-" + n + ".png")
|
||||
item.AddSummary(`item k <a href="http://example.com">example.com</a>`)
|
||||
// add a Download to the Item
|
||||
item.AddEnclosure("http://example.com/"+n+".mp3", podcast.MP3, 55*(i+1))
|
||||
|
||||
// add the Item and check for validation errors
|
||||
if _, err := p.AddItem(item); err != nil {
|
||||
os.Stderr.WriteString("item validation error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Podcast.Encode writes to an io.Writer
|
||||
if err := p.Encode(os.Stdout); err != nil {
|
||||
fmt.Println("error writing to stdout:", err.Error())
|
||||
}
|
||||
|
||||
// Output:
|
||||
// <?xml version="1.0" encoding="UTF-8"?>
|
||||
// <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
|
||||
// <channel>
|
||||
// <title>Sample Podcasts</title>
|
||||
// <link>http://example.com/</link>
|
||||
// <description>An example Podcast</description>
|
||||
// <generator>go podcast v1.3.1 (github.com/eduncan911/podcast)</generator>
|
||||
// <language>en-us</language>
|
||||
// <lastBuildDate>Mon, 06 Feb 2017 08:21:52 +0000</lastBuildDate>
|
||||
// <managingEditor>jane.doe@example.com (Jane Doe)</managingEditor>
|
||||
// <pubDate>Wed, 01 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <image>
|
||||
// <url>http://example.com/podcast.jpg</url>
|
||||
// <title>Sample Podcasts</title>
|
||||
// <link>http://example.com/</link>
|
||||
// </image>
|
||||
// <atom:link href="http://example.com/atom.rss" rel="self" type="application/rss+xml"></atom:link>
|
||||
// <itunes:author>jane.doe@example.com (Jane Doe)</itunes:author>
|
||||
// <itunes:subtitle>A simple Podcast</itunes:subtitle>
|
||||
// <itunes:summary><![CDATA[link <a href="http://example.com">example.com</a>]]></itunes:summary>
|
||||
// <itunes:image href="http://example.com/podcast.jpg"></itunes:image>
|
||||
// <item>
|
||||
// <guid>http://example.com/9.mp3</guid>
|
||||
// <title>Episode 9</title>
|
||||
// <link>http://example.com/9.mp3</link>
|
||||
// <description>Description for Episode 9</description>
|
||||
// <pubDate>Mon, 13 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <enclosure url="http://example.com/9.mp3" length="550" type="audio/mpeg"></enclosure>
|
||||
// <itunes:author>jane.doe@example.com (Jane Doe)</itunes:author>
|
||||
// <itunes:subtitle>A simple episode 9</itunes:subtitle>
|
||||
// <itunes:summary><![CDATA[item k <a href="http://example.com">example.com</a>]]></itunes:summary>
|
||||
// <itunes:image href="http://example.com/episode-9.png"></itunes:image>
|
||||
// </item>
|
||||
// <item>
|
||||
// <guid>http://example.com/10.mp3</guid>
|
||||
// <title>Episode 10</title>
|
||||
// <link>http://example.com/10.mp3</link>
|
||||
// <description>Description for Episode 10</description>
|
||||
// <pubDate>Tue, 14 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <enclosure url="http://example.com/10.mp3" length="605" type="audio/mpeg"></enclosure>
|
||||
// <itunes:author>jane.doe@example.com (Jane Doe)</itunes:author>
|
||||
// <itunes:subtitle>A simple episode 10</itunes:subtitle>
|
||||
// <itunes:summary><![CDATA[item k <a href="http://example.com">example.com</a>]]></itunes:summary>
|
||||
// <itunes:image href="http://example.com/episode-10.png"></itunes:image>
|
||||
// </item>
|
||||
// </channel>
|
||||
// </rss>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Imported Packages](#pkg-imports)
|
||||
|
@ -364,6 +617,29 @@ func (i *Item) AddDuration(durationInSeconds int64)
|
|||
```
|
||||
AddDuration adds the duration to the iTunes duration field.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
i := podcast.Item{
|
||||
Title: "item title",
|
||||
Description: "item desc",
|
||||
Link: "item link",
|
||||
}
|
||||
d := int64(533)
|
||||
|
||||
// add the Duration in Seconds
|
||||
i.AddDuration(d)
|
||||
|
||||
fmt.Println(i.IDuration)
|
||||
// Output:
|
||||
// 8:53
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Item.AddEnclosure">func</a> (\*Item) [AddEnclosure](./item.go#L54-L55)
|
||||
``` go
|
||||
func (i *Item) AddEnclosure(
|
||||
|
@ -393,6 +669,42 @@ AddPubDate adds the datetime as a parsed PubDate.
|
|||
|
||||
UTC time is used by default.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", nil, nil)
|
||||
i := podcast.Item{
|
||||
Title: "item title",
|
||||
Description: "item desc",
|
||||
Link: "item link",
|
||||
}
|
||||
d := pubDate.AddDate(0, 0, -11)
|
||||
|
||||
// add the pub date
|
||||
i.AddPubDate(&d)
|
||||
|
||||
// before adding
|
||||
if i.PubDate != nil {
|
||||
fmt.Println(i.PubDateFormatted, *i.PubDate)
|
||||
}
|
||||
|
||||
// this should not override with Podcast.PubDate
|
||||
if _, err := p.AddItem(i); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// after adding item
|
||||
fmt.Println(i.PubDateFormatted, *i.PubDate)
|
||||
// Output:
|
||||
// Tue, 24 Jan 2017 08:21:52 +0000 2017-01-24 08:21:52 +0000 UTC
|
||||
// Tue, 24 Jan 2017 08:21:52 +0000 2017-01-24 08:21:52 +0000 UTC
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Item.AddSummary">func</a> (\*Item) [AddSummary](./item.go#L92)
|
||||
``` go
|
||||
func (i *Item) AddSummary(summary string)
|
||||
|
@ -458,6 +770,26 @@ New instantiates a Podcast with required parameters.
|
|||
Nil-able fields are optional but recommended as they are formatted
|
||||
to the expected proper formats.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
ti, l, d := "title", "link", "description"
|
||||
|
||||
// instantiate a new Podcast
|
||||
p := podcast.New(ti, l, d, &pubDate, &updatedDate)
|
||||
|
||||
fmt.Println(p.Title, p.Link, p.Description, p.Language)
|
||||
fmt.Println(p.PubDate, p.LastBuildDate)
|
||||
// Output:
|
||||
// title link description en-us
|
||||
// Sat, 04 Feb 2017 08:21:52 +0000 Mon, 06 Feb 2017 08:21:52 +0000
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.AddAtomLink">func</a> (\*Podcast) [AddAtomLink](./podcast.go#L94)
|
||||
``` go
|
||||
func (p *Podcast) AddAtomLink(href string)
|
||||
|
@ -470,6 +802,26 @@ func (p *Podcast) AddAuthor(name, email string)
|
|||
```
|
||||
AddAuthor adds the specified Author to the podcast.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", nil, nil)
|
||||
|
||||
// add the Author
|
||||
p.AddAuthor("the name", "me@test.com")
|
||||
|
||||
fmt.Println(p.ManagingEditor)
|
||||
fmt.Println(p.IAuthor)
|
||||
// Output:
|
||||
// me@test.com (the name)
|
||||
// me@test.com (the name)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.AddCategory">func</a> (\*Podcast) [AddCategory](./podcast.go#L183)
|
||||
``` go
|
||||
func (p *Podcast) AddCategory(category string, subCategories []string)
|
||||
|
@ -553,6 +905,28 @@ as follows.
|
|||
* Tech News
|
||||
* TV & Film
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", nil, nil)
|
||||
|
||||
// add the Category
|
||||
p.AddCategory("Bombay", nil)
|
||||
p.AddCategory("American", []string{"Longhair", "Shorthair"})
|
||||
p.AddCategory("Siamese", nil)
|
||||
|
||||
fmt.Println(len(p.ICategories), len(p.ICategories[1].ICategories))
|
||||
fmt.Println(p.Category)
|
||||
// Output:
|
||||
// 3 2
|
||||
// Bombay,American,Siamese
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.AddImage">func</a> (\*Podcast) [AddImage](./podcast.go#L214)
|
||||
``` go
|
||||
func (p *Podcast) AddImage(url string)
|
||||
|
@ -566,6 +940,28 @@ extensions (.jpg, .png), and in the RGB colorspace. To optimize
|
|||
images for mobile devices, Apple recommends compressing your
|
||||
image files.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", nil, nil)
|
||||
|
||||
// add the Image
|
||||
p.AddImage("http://example.com/image.jpg")
|
||||
|
||||
if p.Image != nil && p.IImage != nil {
|
||||
fmt.Println(p.Image.URL)
|
||||
fmt.Println(p.IImage.HREF)
|
||||
}
|
||||
// Output:
|
||||
// http://example.com/image.jpg
|
||||
// http://example.com/image.jpg
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.AddItem">func</a> (\*Podcast) [AddItem](./podcast.go#L267)
|
||||
``` go
|
||||
func (p *Podcast) AddItem(i Item) (int, error)
|
||||
|
@ -611,6 +1007,52 @@ Recommendations:
|
|||
* For specifications of itunes tags, see:
|
||||
<a href="https://help.apple.com/itc/podcasts_connect/#/itcb54353390">https://help.apple.com/itc/podcasts_connect/#/itcb54353390</a>
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", &pubDate, &updatedDate)
|
||||
p.AddAuthor("the name", "me@test.com")
|
||||
p.AddImage("http://example.com/image.jpg")
|
||||
|
||||
// create an Item
|
||||
date := pubDate.AddDate(0, 0, 77)
|
||||
item := podcast.Item{
|
||||
Title: "Episode 1",
|
||||
Description: "Description for Episode 1",
|
||||
ISubtitle: "A simple episode 1",
|
||||
PubDate: &date,
|
||||
}
|
||||
item.AddEnclosure(
|
||||
"http://example.com/1.mp3",
|
||||
podcast.MP3,
|
||||
183,
|
||||
)
|
||||
item.AddSummary("See more at <a href=\"http://example.com\">Here</a>")
|
||||
|
||||
// add the Item
|
||||
if _, err := p.AddItem(item); err != nil {
|
||||
fmt.Println("item validation error: " + err.Error())
|
||||
}
|
||||
|
||||
if len(p.Items) != 1 {
|
||||
fmt.Println("expected 1 item in the collection")
|
||||
}
|
||||
pp := p.Items[0]
|
||||
fmt.Println(
|
||||
pp.GUID, pp.Title, pp.Link, pp.Description, pp.Author,
|
||||
pp.AuthorFormatted, pp.Category, pp.Comments, pp.Source,
|
||||
pp.PubDate, pp.PubDateFormatted, *pp.Enclosure,
|
||||
pp.IAuthor, pp.IDuration, pp.IExplicit, pp.IIsClosedCaptioned,
|
||||
pp.IOrder, pp.ISubtitle, pp.ISummary)
|
||||
// Output:
|
||||
// http://example.com/1.mp3 Episode 1 http://example.com/1.mp3 Description for Episode 1 &{{ } me@test.com (the name)} 2017-04-22 08:21:52 +0000 UTC Sat, 22 Apr 2017 08:21:52 +0000 {{ } http://example.com/1.mp3 183 183 audio/mpeg audio/mpeg} me@test.com (the name) A simple episode 1 &{{ } See more at <a href="http://example.com">Here</a>}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.AddLastBuildDate">func</a> (\*Podcast) [AddLastBuildDate](./podcast.go#L344)
|
||||
``` go
|
||||
func (p *Podcast) AddLastBuildDate(datetime *time.Time)
|
||||
|
@ -619,6 +1061,24 @@ AddLastBuildDate adds the datetime as a parsed PubDate.
|
|||
|
||||
UTC time is used by default.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", nil, nil)
|
||||
d := pubDate.AddDate(0, 0, -7)
|
||||
|
||||
p.AddLastBuildDate(&d)
|
||||
|
||||
fmt.Println(p.LastBuildDate)
|
||||
// Output:
|
||||
// Sat, 28 Jan 2017 08:21:52 +0000
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.AddPubDate">func</a> (\*Podcast) [AddPubDate](./podcast.go#L337)
|
||||
``` go
|
||||
func (p *Podcast) AddPubDate(datetime *time.Time)
|
||||
|
@ -627,6 +1087,24 @@ AddPubDate adds the datetime as a parsed PubDate.
|
|||
|
||||
UTC time is used by default.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", nil, nil)
|
||||
d := pubDate.AddDate(0, 0, -5)
|
||||
|
||||
p.AddPubDate(&d)
|
||||
|
||||
fmt.Println(p.PubDate)
|
||||
// Output:
|
||||
// Mon, 30 Jan 2017 08:21:52 +0000
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.AddSubTitle">func</a> (\*Podcast) [AddSubTitle](./podcast.go#L353)
|
||||
``` go
|
||||
func (p *Podcast) AddSubTitle(subTitle string)
|
||||
|
@ -648,12 +1126,122 @@ Limit: 4000 characters
|
|||
Note that this field is a CDATA encoded field which allows for rich text
|
||||
such as html links: `<a href="<a href="http://www.apple.com">http://www.apple.com</a>">Apple</a>`.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New("title", "link", "description", nil, nil)
|
||||
|
||||
// add a summary
|
||||
p.AddSummary(`A very cool podcast with a long summary!
|
||||
|
||||
See more at our website: <a href="http://example.com">example.com</a>
|
||||
`)
|
||||
|
||||
if p.ISummary != nil {
|
||||
fmt.Println(p.ISummary.Text)
|
||||
}
|
||||
// Output:
|
||||
// A very cool podcast with a long summary!
|
||||
//
|
||||
// See more at our website: <a href="http://example.com">example.com</a>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.Bytes">func</a> (\*Podcast) [Bytes](./podcast.go#L386)
|
||||
``` go
|
||||
func (p *Podcast) Bytes() []byte
|
||||
```
|
||||
Bytes returns an encoded []byte slice.
|
||||
|
||||
#### Example:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand code.</summary>
|
||||
|
||||
```go
|
||||
p := podcast.New(
|
||||
"eduncan911 Podcasts",
|
||||
"http://eduncan911.com/",
|
||||
"An example Podcast",
|
||||
&pubDate, &updatedDate,
|
||||
)
|
||||
p.AddAuthor("Jane Doe", "me@janedoe.com")
|
||||
p.AddImage("http://janedoe.com/i.jpg")
|
||||
p.AddSummary(`A very cool podcast with a long summary using Bytes()!
|
||||
|
||||
See more at our website: <a href="http://example.com">example.com</a>
|
||||
`)
|
||||
|
||||
for i := int64(5); i < 7; i++ {
|
||||
n := strconv.FormatInt(i, 10)
|
||||
d := pubDate.AddDate(0, 0, int(i+3))
|
||||
|
||||
item := podcast.Item{
|
||||
Title: "Episode " + n,
|
||||
Link: "http://example.com/" + n + ".mp3",
|
||||
Description: "Description for Episode " + n,
|
||||
PubDate: &d,
|
||||
}
|
||||
if _, err := p.AddItem(item); err != nil {
|
||||
fmt.Println(item.Title, ": error", err.Error())
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// call Podcast.Bytes() to return a byte array
|
||||
os.Stdout.Write(p.Bytes())
|
||||
|
||||
// Output:
|
||||
// <?xml version="1.0" encoding="UTF-8"?>
|
||||
// <rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
|
||||
// <channel>
|
||||
// <title>eduncan911 Podcasts</title>
|
||||
// <link>http://eduncan911.com/</link>
|
||||
// <description>An example Podcast</description>
|
||||
// <generator>go podcast v1.3.1 (github.com/eduncan911/podcast)</generator>
|
||||
// <language>en-us</language>
|
||||
// <lastBuildDate>Mon, 06 Feb 2017 08:21:52 +0000</lastBuildDate>
|
||||
// <managingEditor>me@janedoe.com (Jane Doe)</managingEditor>
|
||||
// <pubDate>Sat, 04 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <image>
|
||||
// <url>http://janedoe.com/i.jpg</url>
|
||||
// <title>eduncan911 Podcasts</title>
|
||||
// <link>http://eduncan911.com/</link>
|
||||
// </image>
|
||||
// <itunes:author>me@janedoe.com (Jane Doe)</itunes:author>
|
||||
// <itunes:summary><![CDATA[A very cool podcast with a long summary using Bytes()!
|
||||
//
|
||||
// See more at our website: <a href="http://example.com">example.com</a>
|
||||
// ]]></itunes:summary>
|
||||
// <itunes:image href="http://janedoe.com/i.jpg"></itunes:image>
|
||||
// <item>
|
||||
// <guid>http://example.com/5.mp3</guid>
|
||||
// <title>Episode 5</title>
|
||||
// <link>http://example.com/5.mp3</link>
|
||||
// <description>Description for Episode 5</description>
|
||||
// <pubDate>Sun, 12 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <itunes:author>me@janedoe.com (Jane Doe)</itunes:author>
|
||||
// <itunes:image href="http://janedoe.com/i.jpg"></itunes:image>
|
||||
// </item>
|
||||
// <item>
|
||||
// <guid>http://example.com/6.mp3</guid>
|
||||
// <title>Episode 6</title>
|
||||
// <link>http://example.com/6.mp3</link>
|
||||
// <description>Description for Episode 6</description>
|
||||
// <pubDate>Mon, 13 Feb 2017 08:21:52 +0000</pubDate>
|
||||
// <itunes:author>me@janedoe.com (Jane Doe)</itunes:author>
|
||||
// <itunes:image href="http://janedoe.com/i.jpg"></itunes:image>
|
||||
// </item>
|
||||
// </channel>
|
||||
// </rss>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### <a name="Podcast.Encode">func</a> (\*Podcast) [Encode](./podcast.go#L391)
|
||||
``` go
|
||||
func (p *Podcast) Encode(w io.Writer) error
|
||||
|
|
52
doc.go
52
doc.go
|
@ -33,17 +33,43 @@
|
|||
//
|
||||
// Extensibility
|
||||
//
|
||||
// In no way are you restricted in having full control over your feeds. You may
|
||||
// choose to skip the API methods and instead use the structs directly. The
|
||||
// fields have been grouped by RSS 2.0 and iTunes fields.
|
||||
// For version 1.x, you are not restricted in having full control over your feeds.
|
||||
// You may choose to skip the API methods and instead use the structs directly. The
|
||||
// fields have been grouped by RSS 2.0 and iTunes fields with iTunes specific fields
|
||||
// all prefixed with the letter `I`.
|
||||
//
|
||||
// iTunes specific fields are all prefixed with the letter `I`.
|
||||
// However, do note that the 2.x version currently in progress will break this
|
||||
// extensibility and enforce API methods going forward. This is to ensure that the feed
|
||||
// can both be marshalled, and unmarshalled back and forth (current 1.x branch can only
|
||||
// be unmarshalled - hence the work for 2.x).
|
||||
//
|
||||
// References
|
||||
// Fuzzing Inputs
|
||||
//
|
||||
// RSS 2.0: https://cyber.harvard.edu/rss/rss.html
|
||||
// `go-fuzz` has been added in 1.4.1, covering all exported API methods. They have been
|
||||
// ran extensively and no issues have come out of them yet (most tests were ran overnight,
|
||||
// over about 11 hours with zero crashes).
|
||||
//
|
||||
// Podcasts: https://help.apple.com/itc/podcasts_connect/#/itca5b22233
|
||||
// If you wish to help fuzz the inputs, with Go 1.13 or later you can run `go-fuzz` on any
|
||||
// of the inputs.
|
||||
//
|
||||
// go get -u github.com/dvyukov/go-fuzz/go-fuzz
|
||||
// go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
// go get -u github.com/eduncan911/podcast
|
||||
// cd $GOPATH/src/github.com/eduncan911/podcast
|
||||
// go-fuzz-build
|
||||
// go-fuzz -func FuzzPodcastAddItem
|
||||
//
|
||||
// To obtain a list of available funcs to pass, just run `go-fuzz` without any parameters:
|
||||
//
|
||||
// $ go-fuzz
|
||||
// 2020/02/13 07:27:32 -func flag not provided, but multiple fuzz functions available:
|
||||
// FuzzItemAddDuration, FuzzItemAddEnclosure, FuzzItemAddImage, FuzzItemAddPubDate,
|
||||
// FuzzItemAddSummary, FuzzPodcastAddAtomLink, FuzzPodcastAddAuthor, FuzzPodcastAddCategory,
|
||||
// FuzzPodcastAddImage, FuzzPodcastAddItem, FuzzPodcastAddLastBuildDate, FuzzPodcastAddPubDate,
|
||||
// FuzzPodcastAddSubTitle, FuzzPodcastAddSummary, FuzzPodcastBytes, FuzzPodcastEncode,
|
||||
// FuzzPodcastNew
|
||||
//
|
||||
// If you do find an issue, please raise an issue immediately and I will quickly address.
|
||||
//
|
||||
// Roadmap
|
||||
//
|
||||
|
@ -70,6 +96,12 @@
|
|||
//
|
||||
// Release Notes
|
||||
//
|
||||
// 1.4.1
|
||||
// * Implement fuzz logic testing of exported funcs (#31)
|
||||
// * Upgrade CICD Pipeline Tooling (#31)
|
||||
// * Update documentation for 1.x and 2.3 (#31)
|
||||
// * Allow godoc2ghmd to run without network (#31)
|
||||
//
|
||||
// 1.4.0
|
||||
// * Add Go Modules, Update vendor folder (#26, #25)
|
||||
// * Add C.I. GitHub Actions (#25)
|
||||
|
@ -113,4 +145,10 @@
|
|||
// * Initial release.
|
||||
// * Full documentation, full examples and complete code coverage.
|
||||
//
|
||||
// References
|
||||
//
|
||||
// RSS 2.0: https://cyber.harvard.edu/rss/rss.html
|
||||
//
|
||||
// Podcasts: https://help.apple.com/itc/podcasts_connect/#/itca5b22233
|
||||
//
|
||||
package podcast
|
||||
|
|
|
@ -0,0 +1,297 @@
|
|||
// +build gofuzz
|
||||
|
||||
package podcast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
)
|
||||
|
||||
func FuzzItemAddDuration(data []byte) int {
|
||||
input, read := binary.Varint(data)
|
||||
if input <= 0 && read == 0 {
|
||||
// error converting []byte into int64
|
||||
return 0
|
||||
}
|
||||
i := newItem(data)
|
||||
|
||||
i.AddDuration(input)
|
||||
|
||||
p := newPodcast(data)
|
||||
if _, err := p.AddItem(i); err != nil {
|
||||
return 0
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzItemAddEnclosure(data []byte) int {
|
||||
url := string(data)
|
||||
length, read := binary.Varint(data)
|
||||
if length <= 0 && read == 0 {
|
||||
// error converting []byte into int64
|
||||
return 0
|
||||
}
|
||||
i := newItem(data)
|
||||
|
||||
i.AddEnclosure(url, MP3, length)
|
||||
|
||||
p := newPodcast(data)
|
||||
if _, err := p.AddItem(i); err != nil {
|
||||
return 0
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzItemAddImage(data []byte) int {
|
||||
i := newItem(data)
|
||||
|
||||
i.AddImage(string(data))
|
||||
|
||||
p := newPodcast(data)
|
||||
if _, err := p.AddItem(i); err != nil {
|
||||
return 0
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzItemAddPubDate(data []byte) int {
|
||||
t := time.Time{}
|
||||
if err := t.GobDecode(data); err != nil {
|
||||
return 0
|
||||
}
|
||||
i := newItem(data)
|
||||
|
||||
i.AddPubDate(&t)
|
||||
|
||||
p := newPodcast(data)
|
||||
if _, err := p.AddItem(i); err != nil {
|
||||
return 0
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzItemAddSummary(data []byte) int {
|
||||
i := newItem(data)
|
||||
|
||||
i.AddSummary(string(data))
|
||||
|
||||
p := newPodcast(data)
|
||||
if _, err := p.AddItem(i); err != nil {
|
||||
return 0
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastNew(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddAtomLink(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
p.AddAtomLink(string(data))
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddAuthor(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
p.AddAuthor(string(data), string(data))
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddCategory(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
subs := make([]string, 3)
|
||||
subs[0] = string(data)
|
||||
subs[1] = string(data)
|
||||
subs[2] = string(data)
|
||||
p.AddCategory(string(data), subs)
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddImage(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
p.AddImage(string(data))
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddItem(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
i := newItem(data)
|
||||
|
||||
if _, err := p.AddItem(i); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddLastBuildDate(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
t := time.Time{}
|
||||
if err := t.GobDecode(data); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
p.AddLastBuildDate(&t)
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddPubDate(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
t := time.Time{}
|
||||
if err := t.GobDecode(data); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
p.AddPubDate(&t)
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddSubTitle(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
p.AddSubTitle(string(data))
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastAddSummary(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
p.AddSummary(string(data))
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastBytes(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
p.Bytes()
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzPodcastEncode(data []byte) int {
|
||||
p := newPodcast(data)
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := p.Encode(&buf); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func newPodcast(data []byte) Podcast {
|
||||
return New(
|
||||
string(data),
|
||||
string(data),
|
||||
string(data),
|
||||
nil, nil)
|
||||
}
|
||||
|
||||
func newItem(data []byte) Item {
|
||||
// Article minimal requirements are:
|
||||
// - Title
|
||||
// - Description
|
||||
// - Link
|
||||
//
|
||||
// Audio minimal requirements are:
|
||||
// - Title
|
||||
// - Description
|
||||
// - Enclosure (HREF, Type and Length all required)
|
||||
//
|
||||
return Item{
|
||||
Title: string(data),
|
||||
Description: string(data),
|
||||
Link: string(data),
|
||||
}
|
||||
}
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.13
|
|||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/dvyukov/go-fuzz v0.0.0-20191206100749-a378175e205c // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dvyukov/go-fuzz v0.0.0-20191206100749-a378175e205c h1:/bXaeEuNG6V0HeyEGw11DYLW5BGsOPlcVRIXbHNUWSo=
|
||||
github.com/dvyukov/go-fuzz v0.0.0-20191206100749-a378175e205c/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
|
|
Loading…
Reference in New Issue