--- /dev/null
+// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
+// Revel Framework source code and usage is governed by a MIT style
+// license that can be found in the LICENSE file.
+
+package revel
+
+import (
+ "github.com/stretchr/testify/assert"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+ "time"
+)
+
+// This tries to benchmark the usual request-serving pipeline to get an overall
+// performance metric.
+//
+// Each iteration runs one mock request to display a hotel's detail page by id.
+//
+// Contributing parts:
+// - Routing
+// - Controller lookup / invocation
+// - Parameter binding
+// - Session, flash, i18n cookies
+// - Render() call magic
+// - Template rendering
+func BenchmarkServeAction(b *testing.B) {
+ benchmarkRequest(b, showRequest)
+}
+
+func BenchmarkServeJson(b *testing.B) {
+ benchmarkRequest(b, jsonRequest)
+}
+
+func BenchmarkServePlaintext(b *testing.B) {
+ benchmarkRequest(b, plaintextRequest)
+}
+
+// This tries to benchmark the static serving overhead when serving an "average
+// size" 7k file.
+func BenchmarkServeStatic(b *testing.B) {
+ benchmarkRequest(b, staticRequest)
+}
+
+func benchmarkRequest(b *testing.B, req *http.Request) {
+ startFakeBookingApp()
+ b.ResetTimer()
+ resp := httptest.NewRecorder()
+ for i := 0; i < b.N; i++ {
+ CurrentEngine.(*GoHttpServer).Handle(resp, req)
+ }
+}
+
+// Test that the booking app can be successfully run for a test.
+func TestFakeServer(t *testing.T) {
+ startFakeBookingApp()
+
+ resp := httptest.NewRecorder()
+
+ // First, test that the expected responses are actually generated
+ CurrentEngine.(*GoHttpServer).Handle(resp, showRequest)
+ if !strings.Contains(resp.Body.String(), "300 Main St.") {
+ t.Errorf("Failed to find hotel address in action response:\n%s", resp.Body)
+ t.FailNow()
+ }
+ resp.Body.Reset()
+
+ CurrentEngine.(*GoHttpServer).Handle(resp, staticRequest)
+ sessvarsSize := getFileSize(t, filepath.Join(BasePath, "public", "js", "sessvars.js"))
+ if int64(resp.Body.Len()) != sessvarsSize {
+ t.Errorf("Expected sessvars.js to have %d bytes, got %d:\n%s", sessvarsSize, resp.Body.Len(), resp.Body)
+ t.FailNow()
+ }
+ resp.Body.Reset()
+
+ CurrentEngine.(*GoHttpServer).Handle(resp, jsonRequest)
+ if !strings.Contains(resp.Body.String(), `"Address":"300 Main St."`) {
+ t.Errorf("Failed to find hotel address in JSON response:\n%s", resp.Body)
+ t.FailNow()
+ }
+ resp.Body.Reset()
+
+ CurrentEngine.(*GoHttpServer).Handle(resp, plaintextRequest)
+ if resp.Body.String() != "Hello, World!" {
+ t.Errorf("Failed to find greeting in plaintext response:\n%s", resp.Body)
+ t.FailNow()
+ }
+
+ resp.Body = nil
+}
+
+func getFileSize(t *testing.T, name string) int64 {
+ fi, err := os.Stat(name)
+ if err != nil {
+ t.Errorf("Unable to stat file:\n%s", name)
+ t.FailNow()
+ }
+ return fi.Size()
+}
+
+// Ensure on app start runs in order
+func TestOnAppStart(t *testing.T) {
+ str := ""
+ a := assert.New(t)
+ OnAppStart(func() {
+ str += " World"
+ }, 2)
+
+ OnAppStart(func() {
+ str += "Hello"
+ }, 1)
+
+ startFakeBookingApp()
+
+ a.Equal("Hello World", str, "Failed to order OnAppStart")
+}
+
+// Ensure on app stop runs in order
+func TestOnAppStop(t *testing.T) {
+ a := assert.New(t)
+ startFakeBookingApp()
+ i := ""
+ OnAppStop(func() {
+ i += "cruel world"
+ t.Logf("i: %v \n", i)
+ }, 2)
+ OnAppStop(func() {
+ i += "goodbye "
+ t.Logf("i: %v \n", i)
+ }, 1)
+ go func() {
+ time.Sleep(2 * time.Second)
+ RaiseEvent(ENGINE_SHUTDOWN_REQUEST, nil)
+ }()
+ Run(0)
+ a.Equal("goodbye cruel world", i, "Did not get shutdown events")
+
+}
+
+var (
+ showRequest, _ = http.NewRequest("GET", "/hotels/3", nil)
+ staticRequest, _ = http.NewRequest("GET", "/public/js/sessvars.js", nil)
+ jsonRequest, _ = http.NewRequest("GET", "/hotels/3/booking", nil)
+ plaintextRequest, _ = http.NewRequest("GET", "/hotels", nil)
+)