Fix LoadHTML* tests (#1559)

Digging into the test code base I've found out that some of the tests for `LoadHTML*` methods are not reliable and efficient. They use timeouts to be sure that goroutine with the server has started. And even more, in old implementation, the server started only once – all the new instances silently failed due to the occupied network port.

Here is a short overview of the proposed changes: 
- it's not necessary to rely on timeouts, the server starts listening synchronously and returns control when it is ready
- once the server is run, it's stopped after a test passes
- dry out http server setup
- magic with empty closure return is eliminated 
- preserve router.RunTLS coverage with integration tests
This commit is contained in:
Sergey Ponomarev 2018-10-16 03:48:41 +03:00 committed by Bo-Yi Wu
parent 524757b81c
commit cfa092f4f0
2 changed files with 165 additions and 113 deletions

View File

@ -6,6 +6,7 @@ package gin
import ( import (
"bufio" "bufio"
"crypto/tls"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net" "net"
@ -20,7 +21,14 @@ import (
) )
func testRequest(t *testing.T, url string) { func testRequest(t *testing.T, url string) {
resp, err := http.Get(url) tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
client := &http.Client{Transport: tr}
resp, err := client.Get(url)
assert.NoError(t, err) assert.NoError(t, err)
defer resp.Body.Close() defer resp.Body.Close()
@ -45,6 +53,22 @@ func TestRunEmpty(t *testing.T) {
testRequest(t, "http://localhost:8080/example") 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) { func TestRunEmptyWithEnv(t *testing.T) {
os.Setenv("PORT", "3123") os.Setenv("PORT", "3123")
router := New() router := New()

View File

@ -10,6 +10,7 @@ import (
"html/template" "html/template"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/httptest"
"reflect" "reflect"
"testing" "testing"
"time" "time"
@ -22,15 +23,14 @@ func formatAsDate(t time.Time) string {
return fmt.Sprintf("%d/%02d/%02d", year, month, day) return fmt.Sprintf("%d/%02d/%02d", year, month, day)
} }
func setupHTMLFiles(t *testing.T, mode string, tls bool) func() { func setupHTMLFiles(t *testing.T, mode string, tls bool, loadMethod func(*Engine)) *httptest.Server {
go func() {
SetMode(mode) SetMode(mode)
router := New() router := New()
router.Delims("{[{", "}]}") router.Delims("{[{", "}]}")
router.SetFuncMap(template.FuncMap{ router.SetFuncMap(template.FuncMap{
"formatAsDate": formatAsDate, "formatAsDate": formatAsDate,
}) })
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl") loadMethod(router)
router.GET("/test", func(c *Context) { router.GET("/test", func(c *Context) {
c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"})
}) })
@ -39,88 +39,89 @@ func setupHTMLFiles(t *testing.T, mode string, tls bool) func() {
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
}) })
}) })
var ts *httptest.Server
if tls { if tls {
// these files generated by `go run $GOROOT/src/crypto/tls/generate_cert.go --host 127.0.0.1` ts = httptest.NewTLSServer(router)
router.RunTLS(":9999", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")
} else { } else {
router.Run(":8888") ts = httptest.NewServer(router)
} }
}()
t.Log("waiting 1 second for server startup") return ts
time.Sleep(1 * time.Second)
return func() {}
} }
func setupHTMLGlob(t *testing.T, mode string, tls bool) func() { func TestLoadHTMLGlobDebugMode(t *testing.T) {
go func() { ts := setupHTMLFiles(
SetMode(mode) t,
router := New() DebugMode,
router.Delims("{[{", "}]}") false,
router.SetFuncMap(template.FuncMap{ func(router *Engine) {
"formatAsDate": formatAsDate,
})
router.LoadHTMLGlob("./testdata/template/*") router.LoadHTMLGlob("./testdata/template/*")
router.GET("/test", func(c *Context) { },
c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) )
}) defer ts.Close()
router.GET("/raw", func(c *Context) {
c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
})
})
if tls {
// these files generated by `go run $GOROOT/src/crypto/tls/generate_cert.go --host 127.0.0.1`
router.RunTLS(":9999", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")
} else {
router.Run(":8888")
}
}()
t.Log("waiting 1 second for server startup")
time.Sleep(1 * time.Second)
return func() {}
}
func TestLoadHTMLGlob(t *testing.T) { res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
td := setupHTMLGlob(t, DebugMode, false)
res, err := http.Get("http://127.0.0.1:8888/test")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLGlob2(t *testing.T) { func TestLoadHTMLGlobTestMode(t *testing.T) {
td := setupHTMLGlob(t, TestMode, false) ts := setupHTMLFiles(
res, err := http.Get("http://127.0.0.1:8888/test") t,
TestMode,
false,
func(router *Engine) {
router.LoadHTMLGlob("./testdata/template/*")
},
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLGlob3(t *testing.T) { func TestLoadHTMLGlobReleaseMode(t *testing.T) {
td := setupHTMLGlob(t, ReleaseMode, false) ts := setupHTMLFiles(
res, err := http.Get("http://127.0.0.1:8888/test") t,
ReleaseMode,
false,
func(router *Engine) {
router.LoadHTMLGlob("./testdata/template/*")
},
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLGlobUsingTLS(t *testing.T) { func TestLoadHTMLGlobUsingTLS(t *testing.T) {
td := setupHTMLGlob(t, DebugMode, true) ts := setupHTMLFiles(
t,
DebugMode,
true,
func(router *Engine) {
router.LoadHTMLGlob("./testdata/template/*")
},
)
defer ts.Close()
// Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error // Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
tr := &http.Transport{ tr := &http.Transport{
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
@ -128,29 +129,33 @@ func TestLoadHTMLGlobUsingTLS(t *testing.T) {
}, },
} }
client := &http.Client{Transport: tr} client := &http.Client{Transport: tr}
res, err := client.Get("https://127.0.0.1:9999/test") res, err := client.Get(fmt.Sprintf("%s/test", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLGlobFromFuncMap(t *testing.T) { func TestLoadHTMLGlobFromFuncMap(t *testing.T) {
time.Now() ts := setupHTMLFiles(
td := setupHTMLGlob(t, DebugMode, false) t,
res, err := http.Get("http://127.0.0.1:8888/raw") DebugMode,
false,
func(router *Engine) {
router.LoadHTMLGlob("./testdata/template/*")
},
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/raw", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "Date: 2017/07/01\n", string(resp)) assert.Equal(t, "Date: 2017/07/01\n", string(resp))
td()
} }
func init() { func init() {
@ -164,59 +169,77 @@ func TestCreateEngine(t *testing.T) {
assert.Empty(t, router.Handlers) assert.Empty(t, router.Handlers)
} }
// func TestLoadHTMLDebugMode(t *testing.T) { func TestLoadHTMLFilesTestMode(t *testing.T) {
// router := New() ts := setupHTMLFiles(
// SetMode(DebugMode) t,
// router.LoadHTMLGlob("*.testtmpl") TestMode,
// r := router.HTMLRender.(render.HTMLDebug) false,
// assert.Empty(t, r.Files) func(router *Engine) {
// assert.Equal(t, "*.testtmpl", r.Glob) router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
// },
// router.LoadHTMLFiles("index.html.testtmpl", "login.html.testtmpl") )
// r = router.HTMLRender.(render.HTMLDebug) defer ts.Close()
// assert.Empty(t, r.Glob)
// assert.Equal(t, []string{"index.html", "login.html"}, r.Files)
// SetMode(TestMode)
// }
func TestLoadHTMLFiles(t *testing.T) { res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
td := setupHTMLFiles(t, TestMode, false)
res, err := http.Get("http://127.0.0.1:8888/test")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLFiles2(t *testing.T) { func TestLoadHTMLFilesDebugMode(t *testing.T) {
td := setupHTMLFiles(t, DebugMode, false) ts := setupHTMLFiles(
res, err := http.Get("http://127.0.0.1:8888/test") t,
DebugMode,
false,
func(router *Engine) {
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
},
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLFiles3(t *testing.T) { func TestLoadHTMLFilesReleaseMode(t *testing.T) {
td := setupHTMLFiles(t, ReleaseMode, false) ts := setupHTMLFiles(
res, err := http.Get("http://127.0.0.1:8888/test") t,
ReleaseMode,
false,
func(router *Engine) {
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
},
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLFilesUsingTLS(t *testing.T) { func TestLoadHTMLFilesUsingTLS(t *testing.T) {
td := setupHTMLFiles(t, TestMode, true) ts := setupHTMLFiles(
t,
TestMode,
true,
func(router *Engine) {
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
},
)
defer ts.Close()
// Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error // Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
tr := &http.Transport{ tr := &http.Transport{
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
@ -224,28 +247,33 @@ func TestLoadHTMLFilesUsingTLS(t *testing.T) {
}, },
} }
client := &http.Client{Transport: tr} client := &http.Client{Transport: tr}
res, err := client.Get("https://127.0.0.1:9999/test") res, err := client.Get(fmt.Sprintf("%s/test", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "<h1>Hello world</h1>", string(resp)) assert.Equal(t, "<h1>Hello world</h1>", string(resp))
td()
} }
func TestLoadHTMLFilesFuncMap(t *testing.T) { func TestLoadHTMLFilesFuncMap(t *testing.T) {
time.Now() ts := setupHTMLFiles(
td := setupHTMLFiles(t, TestMode, false) t,
res, err := http.Get("http://127.0.0.1:8888/raw") TestMode,
false,
func(router *Engine) {
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
},
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/raw", ts.URL))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
resp, _ := ioutil.ReadAll(res.Body) resp, _ := ioutil.ReadAll(res.Body)
assert.Equal(t, "Date: 2017/07/01\n", string(resp)) assert.Equal(t, "Date: 2017/07/01\n", string(resp))
td()
} }
func TestAddRoute(t *testing.T) { func TestAddRoute(t *testing.T) {