123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580 |
- /*
- * DudelDu
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the MIT
- * License, If a copy of the MIT License was not distributed with this
- * file, You can obtain one at https://opensource.org/licenses/MIT.
- */
- package playlist
- import (
- "flag"
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "sync"
- "testing"
- "devt.de/krotik/common/fileutil"
- "devt.de/krotik/common/httputil"
- "devt.de/krotik/dudeldu"
- )
- const TESTPORT = ":9092"
- const pdir = "playlisttest"
- const testPlaylist = `
- /*
- Test comment
- */
- {
- "/testpath" : [
- {
- "artist" : "artist1", // 1234
- "title" : "test1",
- "path" : "playlisttest/test1.mp3"
- },
- {
- "artist" : "artist2",
- "title" : "test2",
- "path" : "playlisttest/test2.nsv"
- },
- {
- "artist" : "artist3",
- "title" : "test3",
- "path" : "playlisttest/test3.xyz"
- }
- ]
- }`
- const testPlaylist2 = `{
- "/testpath" : [
- {
- "artist" : "artist1",
- "title" : "test1",
- "path" : "playlisttest/test1.mp3"
- },
- {
- "artist" : "artist2",
- "title" : "test2",
- "path" : "playlisttest/test2.nsv"
- },
- {
- "artist" : "artist2",
- "title" : "test2",
- "path" : "playlisttest/nonexist"
- },
- {
- "artist" : "artist3",
- "title" : "test3",
- "path" : "playlisttest/test3.xyz"
- },
- {
- "artist" : "artist4",
- "title" : "test4",
- "path" : "http://localhost:9092/songs/song1.mp3"
- }
- ]
- }`
- const invalidFileName = "**" + string(0x0)
- func TestMain(m *testing.M) {
- flag.Parse()
- // Setup
- if res, _ := fileutil.PathExists(pdir); res {
- os.RemoveAll(pdir)
- }
- err := os.Mkdir(pdir, 0770)
- if err != nil {
- fmt.Print("Could not create test directory:", err.Error())
- os.Exit(1)
- }
- // Run the tests
- res := m.Run()
- // Teardown
- err = os.RemoveAll(pdir)
- if err != nil {
- fmt.Print("Could not remove test directory:", err.Error())
- }
- os.Exit(res)
- }
- func TestFilePlaylist(t *testing.T) {
- // Set up
- hs, wg := startServer()
- if hs == nil {
- return
- }
- defer func() {
- stopServer(hs, wg)
- }()
- http.HandleFunc("/songs/song1.mp3", func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("songdata123"))
- })
- err := ioutil.WriteFile(pdir+"/test1.json", []byte(testPlaylist), 0644)
- if err != nil {
- t.Error(err)
- return
- }
- err = ioutil.WriteFile(pdir+"/test2.json", []byte(testPlaylist2), 0644)
- if err != nil {
- t.Error(err)
- return
- }
- err = ioutil.WriteFile(pdir+"/test1invalid.json", []byte(testPlaylist[2:]), 0644)
- if err != nil {
- t.Error(err)
- return
- }
- err = ioutil.WriteFile(pdir+"/test1.mp3", []byte("123"), 0644)
- if err != nil {
- t.Error(err)
- return
- }
- err = ioutil.WriteFile(pdir+"/test2.nsv", []byte("456789"), 0644)
- if err != nil {
- t.Error(err)
- return
- }
- err = ioutil.WriteFile(pdir+"/test3.xyz", []byte("AB"), 0644)
- if err != nil {
- t.Error(err)
- return
- }
- // Load invalid factory
- _, err = NewFilePlaylistFactory(invalidFileName, "")
- if err == nil {
- t.Error(err)
- return
- }
- _, err = NewFilePlaylistFactory(pdir+"/test1invalid.json", "")
- if err.Error() != "invalid character '*' looking for beginning of value" {
- t.Error(err)
- return
- }
- // Create playlist factory
- plf, err := NewFilePlaylistFactory(pdir+"/test1.json", "")
- if err != nil {
- t.Error(err)
- return
- }
- // Request non-existing path
- res := plf.Playlist("/nonexist", false)
- if res != nil {
- t.Error("Non existing path should return nil")
- return
- }
- // Get existing playlist
- pl := plf.Playlist("/testpath", false)
- defer pl.Close()
- if pl == nil {
- t.Error("Playlist should exist")
- return
- }
- if pl.Name() != "/testpath" {
- t.Error("Unexpected playlist name:", pl.Name())
- return
- }
- FrameSize = 2
- if pl.ContentType() != "audio/mpeg" {
- t.Error("Unexpected content type:", pl.ContentType())
- return
- }
- if pl.Artist() != "artist1" {
- t.Error("Unexpected artist:", pl.ContentType())
- return
- }
- if pl.Title() != "test1" {
- t.Error("Unexpected title:", pl.ContentType())
- return
- }
- // Test close call
- frame, err := pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "12" {
- t.Error("Unexpected frame:", string(frame))
- return
- }
- pl.Close()
- // Make the frame pool run dry if more than one byte array is used
- pl.(*FilePlaylist).framePool = &sync.Pool{}
- pl.(*FilePlaylist).framePool.Put(make([]byte, 2, 2))
- // Check that the right frames are returned
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "12" {
- t.Error("Unexpected frame:", string(frame))
- return
- }
- pl.ReleaseFrame(frame)
- if pl.Title() != "test1" || pl.Artist() != "artist1" {
- t.Error("Unexpected title/artist:", pl.Title(), pl.Artist())
- return
- }
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "34" {
- t.Error("Unexpected frame:", string(frame))
- return
- }
- pl.ReleaseFrame(frame)
- if pl.Title() != "test2" || pl.Artist() != "artist2" {
- t.Error("Unexpected title/artist:", pl.Title(), pl.Artist())
- return
- }
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "56" {
- t.Error("Unexpected frame:", string(frame))
- return
- }
- pl.ReleaseFrame(frame)
- if pl.Title() != "test2" || pl.Artist() != "artist2" {
- t.Error("Unexpected title/artist:", pl.Title(), pl.Artist())
- return
- }
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "78" {
- t.Error("Unexpected frame:", string(frame))
- return
- }
- pl.ReleaseFrame(frame)
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "9A" {
- t.Error("Unexpected frame:", string(frame))
- return
- }
- pl.ReleaseFrame(frame)
- if pl.Title() != "test3" || pl.Artist() != "artist3" {
- t.Error("Unexpected title/artist:", pl.Title(), pl.Artist())
- return
- }
- // Check frame pool
- if pl.(*FilePlaylist).framePool.Get() == nil {
- t.Error("Frame pool should have an entry")
- return
- }
- if pl.(*FilePlaylist).framePool.Get() != nil {
- t.Error("Frame pool should have no entry")
- return
- }
- // Put again one byte array back
- pl.(*FilePlaylist).framePool.Put(make([]byte, 2, 2))
- frame, err = pl.Frame()
- if err != dudeldu.ErrPlaylistEnd {
- t.Error(err)
- return
- } else if string(frame) != "B" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- pl.ReleaseFrame(frame)
- // Check that the byte array was NOT put back into the pool
- if pl.(*FilePlaylist).framePool.Get() != nil {
- t.Error("Frame pool should have no entry")
- return
- }
- if !pl.Finished() {
- t.Error("Playlist should be finished")
- return
- }
- // Change the last file
- err = ioutil.WriteFile(pdir+"/test3.xyz", []byte("A"), 0644)
- if err != nil {
- t.Error(err)
- return
- }
- // Make the frame pool normal again
- pl.(*FilePlaylist).framePool = &sync.Pool{New: func() interface{} { return make([]byte, FrameSize, FrameSize) }}
- // Increase the framesize
- FrameSize = 5
- pl.Close()
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "12345" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- // Check that the content type is unknown
- if pl.ContentType() != "video/nsv" {
- t.Error("Content type should be nsv not:", pl.ContentType())
- return
- }
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "6789A" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- if pl.ContentType() != "audio" {
- t.Error("Content type should be generic not:", pl.ContentType())
- return
- }
- frame, err = pl.Frame()
- if err != dudeldu.ErrPlaylistEnd {
- t.Error(err)
- return
- } else if string(frame) != "" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- if !pl.Finished() {
- t.Error("Playlist should be finished")
- return
- }
- // Increase the framesize
- FrameSize = 10
- pl.Close()
- frame, err = pl.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "123456789A" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- frame, err = pl.Frame()
- if err != dudeldu.ErrPlaylistEnd {
- t.Error(err)
- return
- } else if string(frame) != "" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- if !pl.Finished() {
- t.Error("Playlist should be finished")
- return
- }
- // Increase the framesize
- FrameSize = 11
- pl.Close()
- frame, err = pl.Frame()
- if err != dudeldu.ErrPlaylistEnd {
- t.Error(err)
- return
- } else if string(frame) != "123456789A" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- if !pl.Finished() {
- t.Error("Playlist should be finished")
- return
- }
- // Check that the playlist has finished indeed
- if _, err := pl.Frame(); err != dudeldu.ErrPlaylistEnd {
- t.Error("Playlist end error expected")
- return
- }
- // Create playlist factory
- plf, err = NewFilePlaylistFactory(pdir+"/test2.json", "")
- if err != nil {
- t.Error(err)
- return
- }
- // Test error
- pl2 := plf.Playlist("/testpath", false)
- defer pl2.Close()
- FrameSize = 6
- frame, err = pl2.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "123456" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- frame, err = pl2.Frame()
- if err.Error() != "open playlisttest/nonexist: The system cannot find the file specified." &&
- err.Error() != "open playlisttest/nonexist: no such file or directory" {
- t.Error(err)
- return
- } else if string(frame) != "789" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- frame, err = pl2.Frame()
- if err != nil {
- t.Error(err)
- return
- } else if string(frame) != "Asongd" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- frame, err = pl2.Frame()
- if err != dudeldu.ErrPlaylistEnd {
- t.Error(err)
- return
- } else if string(frame) != "ata123" {
- t.Error("Unexpected frame:", string(frame), frame)
- return
- }
- // Make sure currentItem does not blow up
- if pl2.Title() != "test4" {
- t.Error("Unexpected result:", pl2.Title())
- return
- }
- // Test shuffling
- pl3 := plf.Playlist("/testpath", true)
- if len(pl3.(*FilePlaylist).data) != len(pl2.(*FilePlaylist).data) {
- t.Error("Length of playlists differ")
- return
- }
- }
- /*
- Start a HTTP test server.
- */
- func startServer() (*httputil.HTTPServer, *sync.WaitGroup) {
- hs := &httputil.HTTPServer{}
- var wg sync.WaitGroup
- wg.Add(1)
- go hs.RunHTTPServer(TESTPORT, &wg)
- wg.Wait()
- // Server is started
- if hs.LastError != nil {
- panic(hs.LastError)
- }
- return hs, &wg
- }
- /*
- Stop a started HTTP test server.
- */
- func stopServer(hs *httputil.HTTPServer, wg *sync.WaitGroup) {
- if hs.Running == true {
- wg.Add(1)
- // Server is shut down
- hs.Shutdown()
- wg.Wait()
- } else {
- panic("Server was not running as expected")
- }
- }
|