// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. package gin import ( "bufio" "crypto/tls" "fmt" "io/ioutil" "net" "net/http" "net/http/httptest" "os" "sync" "testing" "time" "github.com/stretchr/testify/assert" ) func testRequest(t *testing.T, url string) { tr := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } client := &http.Client{Transport: tr} resp, err := client.Get(url) assert.NoError(t, err) defer resp.Body.Close() body, ioerr := ioutil.ReadAll(resp.Body) assert.NoError(t, ioerr) assert.Equal(t, "it worked", string(body), "resp body should match") assert.Equal(t, "200 OK", resp.Status, "should get a 200") } func TestRunEmpty(t *testing.T) { os.Setenv("PORT", "") router := New() go func() { router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) assert.NoError(t, router.Run()) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) assert.Error(t, router.Run(":8080")) testRequest(t, "http://localhost:8080/example") } func TestRunTLS(t *testing.T) { router := New() go func() { router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) assert.NoError(t, router.RunTLS(":8443", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) assert.Error(t, router.RunTLS(":8443", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) testRequest(t, "https://localhost:8443/example") } func TestRunEmptyWithEnv(t *testing.T) { os.Setenv("PORT", "3123") router := New() go func() { router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) assert.NoError(t, router.Run()) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) assert.Error(t, router.Run(":3123")) testRequest(t, "http://localhost:3123/example") } func TestRunTooMuchParams(t *testing.T) { router := New() assert.Panics(t, func() { router.Run("2", "2") }) } func TestRunWithPort(t *testing.T) { router := New() go func() { router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) assert.NoError(t, router.Run(":5150")) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) assert.Error(t, router.Run(":5150")) testRequest(t, "http://localhost:5150/example") } func TestUnixSocket(t *testing.T) { router := New() go func() { router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) assert.NoError(t, router.RunUnix("/tmp/unix_unit_test")) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) c, err := net.Dial("unix", "/tmp/unix_unit_test") assert.NoError(t, err) fmt.Fprint(c, "GET /example HTTP/1.0\r\n\r\n") scanner := bufio.NewScanner(c) var response string for scanner.Scan() { response += scanner.Text() } assert.Contains(t, response, "HTTP/1.0 200", "should get a 200") assert.Contains(t, response, "it worked", "resp body should match") } func TestBadUnixSocket(t *testing.T) { router := New() assert.Error(t, router.RunUnix("#/tmp/unix_unit_test")) } func TestFileDescriptor(t *testing.T) { router := New() addr, err := net.ResolveTCPAddr("tcp", "localhost:0") assert.NoError(t, err) listener, err := net.ListenTCP("tcp", addr) assert.NoError(t, err) socketFile, err := listener.File() assert.NoError(t, err) go func() { router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) assert.NoError(t, router.RunFd(int(socketFile.Fd()))) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) c, err := net.Dial("tcp", listener.Addr().String()) assert.NoError(t, err) fmt.Fprintf(c, "GET /example HTTP/1.0\r\n\r\n") scanner := bufio.NewScanner(c) var response string for scanner.Scan() { response += scanner.Text() } assert.Contains(t, response, "HTTP/1.0 200", "should get a 200") assert.Contains(t, response, "it worked", "resp body should match") } func TestBadFileDescriptor(t *testing.T) { router := New() assert.Error(t, router.RunFd(0)) } func TestWithHttptestWithAutoSelectedPort(t *testing.T) { router := New() router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) ts := httptest.NewServer(router) defer ts.Close() testRequest(t, ts.URL+"/example") } func TestConcurrentHandleContext(t *testing.T) { router := New() router.GET("/", func(c *Context) { c.Request.URL.Path = "/example" router.HandleContext(c) }) router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) ts := httptest.NewServer(router) defer ts.Close() var wg sync.WaitGroup iterations := 200 wg.Add(iterations) for i := 0; i < iterations; i++ { go func() { testRequest(t, ts.URL+"/") wg.Done() }() } wg.Wait() } // func TestWithHttptestWithSpecifiedPort(t *testing.T) { // router := New() // router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) // l, _ := net.Listen("tcp", ":8033") // ts := httptest.Server{ // Listener: l, // Config: &http.Server{Handler: router}, // } // ts.Start() // defer ts.Close() // testRequest(t, "http://localhost:8033/example") // }