mirror of
				https://github.com/gin-gonic/gin.git
				synced 2025-11-04 01:02:14 +08:00 
			
		
		
		
	- Update minimum required Go version from 1.23 to 1.24 throughout documentation, warnings, and tests - Remove Go 1.23 from the GitHub Actions workflow matrix - Change single quotes to double quotes for consistency in workflow configuration Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
		
			
				
	
	
		
			169 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2014 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 (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"html/template"
 | 
						|
	"io"
 | 
						|
	"log"
 | 
						|
	"net/http"
 | 
						|
	"os"
 | 
						|
	"runtime"
 | 
						|
	"strings"
 | 
						|
	"sync"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
	"github.com/stretchr/testify/require"
 | 
						|
)
 | 
						|
 | 
						|
// TODO
 | 
						|
// func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) {
 | 
						|
// func debugPrint(format string, values ...any) {
 | 
						|
 | 
						|
func TestIsDebugging(t *testing.T) {
 | 
						|
	SetMode(DebugMode)
 | 
						|
	assert.True(t, IsDebugging())
 | 
						|
	SetMode(ReleaseMode)
 | 
						|
	assert.False(t, IsDebugging())
 | 
						|
	SetMode(TestMode)
 | 
						|
	assert.False(t, IsDebugging())
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrint(t *testing.T) {
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		SetMode(ReleaseMode)
 | 
						|
		debugPrint("DEBUG this!")
 | 
						|
		SetMode(TestMode)
 | 
						|
		debugPrint("DEBUG this!")
 | 
						|
		SetMode(DebugMode)
 | 
						|
		debugPrint("these are %d %s", 2, "error messages")
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	assert.Equal(t, "[GIN-debug] these are 2 error messages\n", re)
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrintError(t *testing.T) {
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		debugPrintError(nil)
 | 
						|
		debugPrintError(errors.New("this is an error"))
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	assert.Equal(t, "[GIN-debug] [ERROR] this is an error\n", re)
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrintRoutes(t *testing.T) {
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		debugPrintRoute(http.MethodGet, "/path/to/route/:param", HandlersChain{func(c *Context) {}, handlerNameTest})
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	assert.Regexp(t, `^\[GIN-debug\] GET    /path/to/route/:param     --> (.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest \(2 handlers\)\n$`, re)
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrintRouteFunc(t *testing.T) {
 | 
						|
	DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
 | 
						|
		fmt.Fprintf(DefaultWriter, "[GIN-debug] %-6s %-40s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers)
 | 
						|
	}
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		debugPrintRoute(http.MethodGet, "/path/to/route/:param1/:param2", HandlersChain{func(c *Context) {}, handlerNameTest})
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	assert.Regexp(t, `^\[GIN-debug\] GET    /path/to/route/:param1/:param2           --> (.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest \(2 handlers\)\n$`, re)
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrintLoadTemplate(t *testing.T) {
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		templ := template.Must(template.New("").Delims("{[{", "}]}").ParseGlob("./testdata/template/hello.tmpl"))
 | 
						|
		debugPrintLoadTemplate(templ)
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	assert.Regexp(t, `^\[GIN-debug\] Loaded HTML Templates \(2\): \n(\t- \n|\t- hello\.tmpl\n){2}\n`, re)
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrintWARNINGSetHTMLTemplate(t *testing.T) {
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		debugPrintWARNINGSetHTMLTemplate()
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	assert.Equal(t, "[GIN-debug] [WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called\nat initialization. ie. before any route is registered or the router is listening in a socket:\n\n\trouter := gin.Default()\n\trouter.SetHTMLTemplate(template) // << good place\n\n", re)
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrintWARNINGDefault(t *testing.T) {
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		debugPrintWARNINGDefault()
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	m, e := getMinVer(runtime.Version())
 | 
						|
	if e == nil && m < ginSupportMinGoVer {
 | 
						|
		assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.24+.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
 | 
						|
	} else {
 | 
						|
		assert.Equal(t, "[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestDebugPrintWARNINGNew(t *testing.T) {
 | 
						|
	re := captureOutput(t, func() {
 | 
						|
		SetMode(DebugMode)
 | 
						|
		debugPrintWARNINGNew()
 | 
						|
		SetMode(TestMode)
 | 
						|
	})
 | 
						|
	assert.Equal(t, "[GIN-debug] [WARNING] Running in \"debug\" mode. Switch to \"release\" mode in production.\n - using env:\texport GIN_MODE=release\n - using code:\tgin.SetMode(gin.ReleaseMode)\n\n", re)
 | 
						|
}
 | 
						|
 | 
						|
func captureOutput(t *testing.T, f func()) string {
 | 
						|
	reader, writer, err := os.Pipe()
 | 
						|
	if err != nil {
 | 
						|
		panic(err)
 | 
						|
	}
 | 
						|
	defaultWriter := DefaultWriter
 | 
						|
	defaultErrorWriter := DefaultErrorWriter
 | 
						|
	defer func() {
 | 
						|
		DefaultWriter = defaultWriter
 | 
						|
		DefaultErrorWriter = defaultErrorWriter
 | 
						|
		log.SetOutput(os.Stderr)
 | 
						|
	}()
 | 
						|
	DefaultWriter = writer
 | 
						|
	DefaultErrorWriter = writer
 | 
						|
	log.SetOutput(writer)
 | 
						|
	out := make(chan string)
 | 
						|
	wg := new(sync.WaitGroup)
 | 
						|
	wg.Add(1)
 | 
						|
	go func() {
 | 
						|
		var buf strings.Builder
 | 
						|
		wg.Done()
 | 
						|
		_, err := io.Copy(&buf, reader)
 | 
						|
		assert.NoError(t, err)
 | 
						|
		out <- buf.String()
 | 
						|
	}()
 | 
						|
	wg.Wait()
 | 
						|
	f()
 | 
						|
	writer.Close()
 | 
						|
	return <-out
 | 
						|
}
 | 
						|
 | 
						|
func TestGetMinVer(t *testing.T) {
 | 
						|
	var m uint64
 | 
						|
	var e error
 | 
						|
	_, e = getMinVer("go1")
 | 
						|
	require.Error(t, e)
 | 
						|
	m, e = getMinVer("go1.1")
 | 
						|
	assert.Equal(t, uint64(1), m)
 | 
						|
	require.NoError(t, e)
 | 
						|
	m, e = getMinVer("go1.1.1")
 | 
						|
	require.NoError(t, e)
 | 
						|
	assert.Equal(t, uint64(1), m)
 | 
						|
	_, e = getMinVer("go1.1.1.1")
 | 
						|
	require.Error(t, e)
 | 
						|
}
 |