[MIRROR: https://git.mills.io/prologic/go-gopher] Gopher (RFC 1436) protocol library for the Go (Golang) programming language supporting both client and server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
4.3 KiB

  1. package gopher_test
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "os"
  7. "testing"
  8. "time"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. "code.as/writefreely/go-gopher"
  12. )
  13. var (
  14. testHost string = "localhost"
  15. testPort int
  16. )
  17. func pickUnusedPort() (int, error) {
  18. addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
  19. if err != nil {
  20. return 0, err
  21. }
  22. l, err := net.ListenTCP("tcp", addr)
  23. if err != nil {
  24. return 0, err
  25. }
  26. port := l.Addr().(*net.TCPAddr).Port
  27. if err := l.Close(); err != nil {
  28. return 0, err
  29. }
  30. return port, nil
  31. }
  32. func TestMain(m *testing.M) {
  33. port, err := pickUnusedPort()
  34. if err != nil {
  35. log.Fatalf("error finding a free port: %s", err)
  36. }
  37. testPort = port
  38. go func() {
  39. gopher.Handle("/", gopher.FileServer(gopher.Dir("./testdata")))
  40. gopher.HandleFunc("/hello", hello)
  41. log.Printf("Test server starting on :%d\n", testPort)
  42. log.Fatal(gopher.ListenAndServe(fmt.Sprintf(":%d", testPort), nil))
  43. }()
  44. // Because it can take some time for the server to spin up
  45. // the tests are inconsistent - they'll fail if the server isn't
  46. // ready, but pass otherwise. This problem seems more pronounced
  47. // when running via the makefile.
  48. //
  49. // It seems like there should be a better way to do this
  50. for attempts := 3; attempts > 0; attempts-- {
  51. _, err := gopher.Get(fmt.Sprintf("gopher://%s:%d", testHost, testPort))
  52. if err == nil {
  53. log.Println("Server ready")
  54. break
  55. }
  56. log.Printf("Server not ready, going to try again in a sec. %v\n", err)
  57. time.Sleep(1 * time.Second)
  58. }
  59. code := m.Run()
  60. os.Exit(code)
  61. }
  62. func hello(w gopher.ResponseWriter, r *gopher.Request) {
  63. w.WriteInfo("Hello World!")
  64. }
  65. func Example_client() {
  66. res, err := gopher.Get("gopher://gopher.floodgap.com")
  67. if err != nil {
  68. log.Fatal(err)
  69. }
  70. fmt.Print(res.Dir.ToText())
  71. }
  72. func Example_server() {
  73. gopher.HandleFunc("/hello", hello)
  74. log.Fatal(gopher.ListenAndServe("localhost:7000", nil))
  75. }
  76. func Example_fileserver() {
  77. gopher.Handle("/", gopher.FileServer(gopher.Dir("/tmp")))
  78. log.Fatal(gopher.ListenAndServe("localhost:7000", nil))
  79. }
  80. func TestGet(t *testing.T) {
  81. assert := assert.New(t)
  82. require := require.New(t)
  83. res, err := gopher.Get(fmt.Sprintf("gopher://%s:%d/1hello", testHost, testPort))
  84. require.NoError(err)
  85. assert.Len(res.Dir.Items, 1)
  86. assert.Equal(res.Dir.Items[0].Type, gopher.INFO)
  87. assert.Equal(res.Dir.Items[0].Description, "Hello World!")
  88. out, err := res.Dir.ToText()
  89. require.NoError(err)
  90. assert.Equal(string(out), "iHello World!\t\terror.host\t1\r\n")
  91. }
  92. func TestFileServer(t *testing.T) {
  93. assert := assert.New(t)
  94. require := require.New(t)
  95. res, err := gopher.Get(fmt.Sprintf("gopher://%s:%d/", testHost, testPort))
  96. require.NoError(err)
  97. assert.Len(res.Dir.Items, 1)
  98. json, err := res.Dir.ToJSON()
  99. require.NoError(err)
  100. log.Println(string(json))
  101. assert.JSONEq(
  102. `{"items":[{"type":"0","description":"hello.txt","selector":"/hello.txt","host":"127.0.0.1","port":7000,"extras":[]}]}`,
  103. string(json))
  104. }
  105. func TestParseItemNull(t *testing.T) {
  106. assert := assert.New(t)
  107. item, err := gopher.ParseItem("")
  108. assert.Nil(item)
  109. assert.Error(err)
  110. }
  111. func TestParseItem(t *testing.T) {
  112. assert := assert.New(t)
  113. require := require.New(t)
  114. item, err := gopher.ParseItem("0foo\t/foo\tlocalhost\t70\r\n")
  115. require.NoError(err)
  116. assert.NotNil(item)
  117. assert.Equal(item, &gopher.Item{
  118. Type: gopher.FILE,
  119. Description: "foo",
  120. Selector: "/foo",
  121. Host: "localhost",
  122. Port: 70,
  123. Extras: []string{},
  124. })
  125. }
  126. func TestParseItemMarshal(t *testing.T) {
  127. assert := assert.New(t)
  128. require := require.New(t)
  129. data := "0foo\t/foo\tlocalhost\t70\r\n"
  130. item, err := gopher.ParseItem(data)
  131. require.NoError(err)
  132. assert.NotNil(item)
  133. assert.Equal(item, &gopher.Item{
  134. Type: gopher.FILE,
  135. Description: "foo",
  136. Selector: "/foo",
  137. Host: "localhost",
  138. Port: 70,
  139. Extras: []string{},
  140. })
  141. data1, err := item.MarshalText()
  142. assert.Nil(err)
  143. assert.Equal(data, string(data1))
  144. }
  145. func TestParseItemMarshalIdempotency(t *testing.T) {
  146. assert := assert.New(t)
  147. require := require.New(t)
  148. data := "0"
  149. item, err := gopher.ParseItem(data)
  150. require.NoError(err)
  151. assert.NotNil(item)
  152. data1, err := item.MarshalText()
  153. assert.Nil(err)
  154. item1, err := gopher.ParseItem(string(data1))
  155. assert.NoError(err)
  156. assert.NotNil(item1)
  157. assert.Equal(item, item1)
  158. }