Skip to content

Commit 35b57a4

Browse files
committed
add small improvements and setup test for pkg/xspf
- add server header to http router - simplify playlist struct - add test for pkg/xspf - improve logging and error handling in cmd/xplay
1 parent da25012 commit 35b57a4

File tree

7 files changed

+87
-24
lines changed

7 files changed

+87
-24
lines changed

.github/workflows/ci-cd.yml

+2-3
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@ jobs:
1313
steps:
1414
- name: Checkout project
1515
uses: actions/checkout@v4
16-
with:
17-
fetch-depth: 0
1816
- name: Set up Go
1917
uses: actions/setup-go@v4
2018
with:
2119
go-version: '1.22'
20+
- name: Run test
21+
run: make test
2222
- name: Build
23-
id: build
2423
run: make
2524
- name: Create Release
2625
uses: ncipollo/release-action@v1

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ LINUX_STATIC=xplay_$(VERSION)_linux_static_x64
77
LD_FLAGS=-s -w -X main.version=$(VERSION)
88
OUTPUT_DIR=build
99

10-
.PHONY: all windows linux staticlinux
10+
.PHONY: all test windows linux staticlinux
1111

1212
default: all
1313

14+
test:
15+
go test --cover -v ./pkg/xspf/
16+
1417
windows:
1518
GOOS=windows GOARCH=amd64 go build -v -o $(OUTPUT_DIR)/$(WINDOWS) -ldflags="$(LD_FLAGS)" ./cmd/xplay
1619

cmd/xplay/xplay.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"flag"
5-
"fmt"
65
"log"
76
"net"
87
"net/http"
@@ -20,13 +19,13 @@ const (
2019

2120
var version = "dev"
2221

23-
func validateDir(path string) {
22+
func validateDir(path string, logger *log.Logger) {
2423
file, err := os.Stat(path)
2524
if err != nil {
26-
panic(err)
25+
logger.Panicln(err)
2726
}
2827
if !file.IsDir() {
29-
panic("not a directory")
28+
logger.Fatalln("Error: Target is not a directory.")
3029
}
3130
}
3231

@@ -44,21 +43,22 @@ func main() {
4443
showVersion := flag.Bool("version", false, "print version and exit")
4544
flag.Parse()
4645

46+
logger := log.New(os.Stdout, "", 0)
4747
if *showVersion {
48-
fmt.Println(version)
48+
logger.Println(version)
4949
return
5050
}
5151

52-
validateDir(mediahandler.MediaDir)
52+
validateDir(mediahandler.MediaDir, logger)
5353
if *output {
5454
if err := mediahandler.WriteToStdout(); err != nil {
55-
panic(err)
55+
logger.Panicln(err)
5656
}
5757
return
5858
}
5959

6060
var handler http.Handler
61-
logger := log.New(os.Stdout, "", log.Ldate|log.Ltime)
61+
logger.SetFlags(log.Ldate | log.Ltime)
6262
if *password != "" {
6363
handler = router.InitAuthRouter(logger, *username, *password)
6464
} else {
@@ -69,12 +69,12 @@ func main() {
6969
if *certFile != "" && *keyFile != "" {
7070
logger.Printf("Starting xplay server %s at https://%s/ ...\n", version, addr)
7171
if err := http.ListenAndServeTLS(addr, *certFile, *keyFile, handler); err != nil {
72-
panic(err)
72+
logger.Panicln(err)
7373
}
7474
} else {
7575
logger.Printf("Starting xplay server %s at http://%s/ ...\n", version, addr)
7676
if err := http.ListenAndServe(addr, handler); err != nil {
77-
panic(err)
77+
logger.Panicln(err)
7878
}
7979
}
8080
}

internal/mediahandler/handler.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ func GetMedia(MediaBaseURL, ImageBaseURL *url.URL) (*xspf.PlayList, error) {
4848
return nil
4949
}
5050
if MediaBaseURL.Scheme != "file" && track.ImageExt != "" {
51-
track.ImageURI = ImageBaseURL.JoinPath(path).String()
51+
track.Image = ImageBaseURL.JoinPath(path).String()
5252
}
5353
}
54-
playList.TrackList.Tracks = append(playList.TrackList.Tracks, *track)
54+
playList.Tracks = append(playList.Tracks, track)
5555
return nil
5656
}); err != nil {
5757
return nil, err

internal/router/router.go

+2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ const (
1313
xspfPath = "/play.xspf"
1414
mediaBasePath = "/media/"
1515
imageBasePath = "/img/"
16+
serverHeader = "xplay"
1617
)
1718

1819
func httpHandler(w http.ResponseWriter, _ *http.Request) {
1920
mediaBaseUrl, _ := url.Parse(mediaBasePath)
2021
imageBaseUrl, _ := url.Parse(imageBasePath)
22+
w.Header().Set("Server", serverHeader)
2123
playList, err := mediahandler.GetMedia(mediaBaseUrl, imageBaseUrl)
2224
if err != nil {
2325
w.WriteHeader(http.StatusInternalServerError)

pkg/xspf/xspf.go

+6-8
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@ const (
1313
)
1414

1515
type PlayList struct {
16-
Title string `xml:"title,omitempty"`
17-
Creator string `xml:"creator,omitempty"`
18-
Date string `xml:"date,omitempty"`
19-
Annotation string `xml:"annotation,omitempty"`
20-
TrackList struct {
21-
Tracks []Track `xml:"track"`
22-
} `xml:"trackList"`
16+
Title string `xml:"title,omitempty"`
17+
Creator string `xml:"creator,omitempty"`
18+
Date string `xml:"date,omitempty"`
19+
Annotation string `xml:"annotation,omitempty"`
20+
Tracks []*Track `xml:"trackList>track"`
2321
}
2422

2523
type Track struct {
@@ -30,7 +28,7 @@ type Track struct {
3028
TrackNum string `xml:"trackNum,omitempty"`
3129
Duration string `xml:"duration,omitempty"`
3230
ImageExt string `xml:"-"`
33-
ImageURI string `xml:"image,omitempty"`
31+
Image string `xml:"image,omitempty"`
3432
Annotation string `xml:"annotation,omitempty"`
3533
}
3634

pkg/xspf/xspf_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package xspf
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"strconv"
7+
"strings"
8+
"testing"
9+
)
10+
11+
const testXml = `
12+
<playlist version="1" xmlns="http://xspf.org/ns/0/">
13+
<title>Playlist</title>
14+
<date>2005-01-08T17:10:47-05:00</date>
15+
<trackList>
16+
<track>
17+
<location>1.mp3</location>
18+
<title>1</title>
19+
</track>
20+
<track>
21+
<location>2.mp3</location>
22+
<title>2</title>
23+
</track>
24+
</trackList>
25+
</playlist>
26+
`
27+
28+
func newTestPlaylist() *PlayList {
29+
list := &PlayList{
30+
Title: "Playlist",
31+
Date: "2005-01-08T17:10:47-05:00",
32+
}
33+
for i := 1; i < 3; i++ {
34+
list.Tracks = append(list.Tracks, &Track{
35+
Location: strconv.Itoa(i) + ".mp3", Title: strconv.Itoa(i), ImageExt: "jpg",
36+
})
37+
}
38+
return list
39+
}
40+
41+
func TestEncodeXspf(t *testing.T) {
42+
buf := bytes.NewBuffer([]byte{})
43+
if err := EncodeXspf(buf, newTestPlaylist()); err != nil {
44+
t.Fatal(err)
45+
}
46+
if strings.Trim(buf.String(), "\n") != strings.Trim(testXml, "\n") {
47+
t.Errorf("Encoded playlist does not match expected:\n%s", buf.String())
48+
}
49+
}
50+
51+
func TestGenerate(t *testing.T) {
52+
if err := Generate(io.Discard, newTestPlaylist()); err != nil {
53+
t.Error(err)
54+
}
55+
}
56+
57+
func TestBufferedGenerate(t *testing.T) {
58+
if _, err := BufferedGenerate(newTestPlaylist()); err != nil {
59+
t.Error(err)
60+
}
61+
}

0 commit comments

Comments
 (0)