dudeldu_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * DudelDu
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package main
  11. import (
  12. "bytes"
  13. "flag"
  14. "fmt"
  15. "io/ioutil"
  16. "os"
  17. "testing"
  18. "devt.de/krotik/common/fileutil"
  19. "devt.de/krotik/common/testutil"
  20. "devt.de/krotik/dudeldu"
  21. "devt.de/krotik/dudeldu/playlist"
  22. )
  23. const testFilePlaylist = `
  24. /*
  25. Test comment
  26. */
  27. {
  28. "/testpath" : [
  29. {
  30. "artist" : "artist1", // 1234
  31. "title" : "test1",
  32. "path" : "playlisttest/test1.mp3"
  33. },
  34. {
  35. "artist" : "artist2",
  36. "title" : "test2",
  37. "path" : "playlisttest/test2.mp4"
  38. },
  39. {
  40. "artist" : "artist3",
  41. "title" : "test3",
  42. "path" : "playlisttest/test3.mp3"
  43. }
  44. ]
  45. }`
  46. const pdir = "playlisttest"
  47. type TestDebugLogger struct {
  48. DebugOutput bool
  49. LogPrint func(v ...interface{})
  50. }
  51. func (ds *TestDebugLogger) IsDebugOutputEnabled() bool {
  52. return ds.DebugOutput
  53. }
  54. func (ds *TestDebugLogger) PrintDebug(v ...interface{}) {
  55. if ds.DebugOutput {
  56. ds.LogPrint(v...)
  57. }
  58. }
  59. func TestRequestHandlerFilePlaylist(t *testing.T) {
  60. // Collect the print output
  61. var out bytes.Buffer
  62. debugLogger := &TestDebugLogger{true, func(v ...interface{}) {
  63. out.WriteString(fmt.Sprint(v...))
  64. out.WriteString("\n")
  65. }}
  66. os.Mkdir(pdir, 0770)
  67. defer func() {
  68. os.RemoveAll(pdir)
  69. }()
  70. ioutil.WriteFile(pdir+"/test.dpl", []byte(testFilePlaylist), 0644)
  71. ioutil.WriteFile(pdir+"/test1.mp3", []byte("abcdefgh"), 0644)
  72. ioutil.WriteFile(pdir+"/test2.mp4", []byte("12345"), 0644)
  73. ioutil.WriteFile(pdir+"/test3.mp3", []byte("???!!!&&&$$$"), 0644)
  74. fac, err := playlist.NewFilePlaylistFactory(pdir+"/test.dpl", "")
  75. if err != nil {
  76. t.Error(err)
  77. return
  78. }
  79. drh := dudeldu.NewDefaultRequestHandler(fac, false, false, "")
  80. drh.SetDebugLogger(debugLogger)
  81. testConn := &testutil.ErrorTestingConnection{}
  82. dudeldu.MetaDataInterval = 5
  83. playlist.FrameSize = 5
  84. drh.ServeRequest(testConn, "/testpath", true, 2, "")
  85. if testConn.Out.String() != ("ICY 200 OK\r\n" +
  86. "Content-Type: audio/mpeg\r\n" +
  87. "icy-name: /testpath\r\n" +
  88. "icy-metadata: 1\r\n" +
  89. "icy-metaint: 5\r\n" +
  90. "\r\n" +
  91. `cdefg` + string(0x02) + `StreamTitle='test2 - artist2';` + string([]byte{0x0, 0x0}) +
  92. `h1234` + string(0x02) + `StreamTitle='test3 - artist3';` + string([]byte{0x0, 0x0}) +
  93. `5???!` + string(0x02) + `StreamTitle='test3 - artist3';` + string([]byte{0x0, 0x0}) +
  94. `!!&&&` + string(0x02) + `StreamTitle='test3 - artist3';` + string([]byte{0x0, 0x0}) +
  95. `$$$`) {
  96. t.Error("Unexpected response:", testConn.Out.String())
  97. return
  98. }
  99. }
  100. func TestDudelDuMain(t *testing.T) {
  101. // Make the fatal a simple print
  102. fatal = print
  103. // Make sure out.txt and test.dpl are removed
  104. defer func() {
  105. if res, _ := fileutil.PathExists("out.txt"); res {
  106. os.Remove("out.txt")
  107. }
  108. if res, _ := fileutil.PathExists("test.dpl"); res {
  109. os.Remove("test.dpl")
  110. }
  111. }()
  112. // Reset flags
  113. flag.CommandLine = &flag.FlagSet{}
  114. // Test usage text
  115. os.Args = []string{"dudeldu", "-?", "-port", "9000", "test"}
  116. flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
  117. if ret, err := execMain(); err != nil || ret != `
  118. DudelDu `[1:]+dudeldu.ProductVersion+`
  119. Usage of dudeldu [options] <playlist>
  120. -? Show this help message
  121. -auth string
  122. Authentication as <user>:<pass>
  123. -debug
  124. Enable extra debugging output
  125. -fqs int
  126. Frame queue size (default 10000)
  127. -host string
  128. Server hostname to listen on (default "127.0.0.1")
  129. -loop
  130. Loop playlists
  131. -port string
  132. Server port to listen on (default "9091")
  133. -pp string
  134. Prefix all paths with a string
  135. -shuffle
  136. Shuffle playlists
  137. -tps int
  138. Thread pool size (default 10)
  139. Authentication can also be defined via the environment variable: DUDELDU_AUTH="<user>:<pass>"
  140. ` {
  141. t.Error("Unexpected output:", "#"+ret+"#", err)
  142. return
  143. }
  144. ioutil.WriteFile("test.dpl", []byte("{}"), 0644)
  145. lookupEnv = func(key string) (string, bool) {
  146. if key == "DUDELDU_AUTH" {
  147. return "web:web", true
  148. }
  149. return "", false
  150. }
  151. os.Args = []string{"dudeldu", "-port", "-1", "test.dpl"}
  152. flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
  153. if ret, err := execMain(); err != nil || ret != `
  154. DudelDu `[1:]+dudeldu.ProductVersion+`
  155. Serving playlist test.dpl on 127.0.0.1:-1
  156. Thread pool size: 10
  157. Frame queue size: 10000
  158. Loop playlist: false
  159. Shuffle playlist: false
  160. Path prefix:
  161. Required authentication: web:web
  162. listen tcp: invalid port -1
  163. Shutting down
  164. ` && ret != `
  165. DudelDu `[1:]+dudeldu.ProductVersion+`
  166. Serving playlist test.dpl on 127.0.0.1:-1
  167. Thread pool size: 10
  168. Frame queue size: 10000
  169. Loop playlist: false
  170. Shuffle playlist: false
  171. Path prefix:
  172. Required authentication: web:web
  173. listen tcp: address -1: invalid port
  174. Shutting down
  175. ` {
  176. t.Error("Unexpected output:", ret, err)
  177. return
  178. }
  179. }
  180. /*
  181. Execute the main function and capture the output.
  182. */
  183. func execMain() (string, error) {
  184. // Exchange stderr to a file
  185. origStdErr := os.Stderr
  186. outFile, err := os.Create("out.txt")
  187. if err != nil {
  188. return "", err
  189. }
  190. defer func() {
  191. outFile.Close()
  192. os.RemoveAll("out.txt")
  193. // Put Stderr back
  194. os.Stderr = origStdErr
  195. }()
  196. os.Stderr = outFile
  197. main()
  198. outFile.Sync()
  199. out, err := ioutil.ReadFile("out.txt")
  200. if err != nil {
  201. return "", err
  202. }
  203. return string(out), nil
  204. }