github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gin/recovery_test.go (about)

     1  // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
     2  // Use of this source code is governed by a MIT style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gin
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"net"
    11  	"github.com/hellobchain/newcryptosm/http"
    12  	"os"
    13  	"strings"
    14  	"syscall"
    15  	"testing"
    16  
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func TestPanicClean(t *testing.T) {
    21  	buffer := new(bytes.Buffer)
    22  	router := New()
    23  	password := "my-super-secret-password"
    24  	router.Use(RecoveryWithWriter(buffer))
    25  	router.GET("/recovery", func(c *Context) {
    26  		c.AbortWithStatus(http.StatusBadRequest)
    27  		panic("Oupps, Houston, we have a problem")
    28  	})
    29  	// RUN
    30  	w := performRequest(router, "GET", "/recovery",
    31  		header{
    32  			Key:   "Host",
    33  			Value: "www.google.com",
    34  		},
    35  		header{
    36  			Key:   "Authorization",
    37  			Value: fmt.Sprintf("Bearer %s", password),
    38  		},
    39  		header{
    40  			Key:   "Content-Type",
    41  			Value: "application/json",
    42  		},
    43  	)
    44  	// TEST
    45  	assert.Equal(t, http.StatusBadRequest, w.Code)
    46  
    47  	// Check the buffer does not have the secret key
    48  	assert.NotContains(t, buffer.String(), password)
    49  }
    50  
    51  // TestPanicInHandler assert that panic has been recovered.
    52  func TestPanicInHandler(t *testing.T) {
    53  	buffer := new(bytes.Buffer)
    54  	router := New()
    55  	router.Use(RecoveryWithWriter(buffer))
    56  	router.GET("/recovery", func(_ *Context) {
    57  		panic("Oupps, Houston, we have a problem")
    58  	})
    59  	// RUN
    60  	w := performRequest(router, "GET", "/recovery")
    61  	// TEST
    62  	assert.Equal(t, http.StatusInternalServerError, w.Code)
    63  	assert.Contains(t, buffer.String(), "panic recovered")
    64  	assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
    65  	assert.Contains(t, buffer.String(), t.Name())
    66  	assert.NotContains(t, buffer.String(), "GET /recovery")
    67  
    68  	// Debug mode prints the request
    69  	SetMode(DebugMode)
    70  	// RUN
    71  	w = performRequest(router, "GET", "/recovery")
    72  	// TEST
    73  	assert.Equal(t, http.StatusInternalServerError, w.Code)
    74  	assert.Contains(t, buffer.String(), "GET /recovery")
    75  
    76  	SetMode(TestMode)
    77  }
    78  
    79  // TestPanicWithAbort assert that panic has been recovered even if context.Abort was used.
    80  func TestPanicWithAbort(t *testing.T) {
    81  	router := New()
    82  	router.Use(RecoveryWithWriter(nil))
    83  	router.GET("/recovery", func(c *Context) {
    84  		c.AbortWithStatus(http.StatusBadRequest)
    85  		panic("Oupps, Houston, we have a problem")
    86  	})
    87  	// RUN
    88  	w := performRequest(router, "GET", "/recovery")
    89  	// TEST
    90  	assert.Equal(t, http.StatusBadRequest, w.Code)
    91  }
    92  
    93  func TestSource(t *testing.T) {
    94  	bs := source(nil, 0)
    95  	assert.Equal(t, []byte("???"), bs)
    96  
    97  	in := [][]byte{
    98  		[]byte("Hello world."),
    99  		[]byte("Hi, gin.."),
   100  	}
   101  	bs = source(in, 10)
   102  	assert.Equal(t, []byte("???"), bs)
   103  
   104  	bs = source(in, 1)
   105  	assert.Equal(t, []byte("Hello world."), bs)
   106  }
   107  
   108  func TestFunction(t *testing.T) {
   109  	bs := function(1)
   110  	assert.Equal(t, []byte("???"), bs)
   111  }
   112  
   113  // TestPanicWithBrokenPipe asserts that recovery specifically handles
   114  // writing responses to broken pipes
   115  func TestPanicWithBrokenPipe(t *testing.T) {
   116  	const expectCode = 204
   117  
   118  	expectMsgs := map[syscall.Errno]string{
   119  		syscall.EPIPE:      "broken pipe",
   120  		syscall.ECONNRESET: "connection reset by peer",
   121  	}
   122  
   123  	for errno, expectMsg := range expectMsgs {
   124  		t.Run(expectMsg, func(t *testing.T) {
   125  
   126  			var buf bytes.Buffer
   127  
   128  			router := New()
   129  			router.Use(RecoveryWithWriter(&buf))
   130  			router.GET("/recovery", func(c *Context) {
   131  				// Start writing response
   132  				c.Header("X-Test", "Value")
   133  				c.Status(expectCode)
   134  
   135  				// Oops. Client connection closed
   136  				e := &net.OpError{Err: &os.SyscallError{Err: errno}}
   137  				panic(e)
   138  			})
   139  			// RUN
   140  			w := performRequest(router, "GET", "/recovery")
   141  			// TEST
   142  			assert.Equal(t, expectCode, w.Code)
   143  			assert.Contains(t, strings.ToLower(buf.String()), expectMsg)
   144  		})
   145  	}
   146  }
   147  
   148  func TestCustomRecoveryWithWriter(t *testing.T) {
   149  	errBuffer := new(bytes.Buffer)
   150  	buffer := new(bytes.Buffer)
   151  	router := New()
   152  	handleRecovery := func(c *Context, err interface{}) {
   153  		errBuffer.WriteString(err.(string))
   154  		c.AbortWithStatus(http.StatusBadRequest)
   155  	}
   156  	router.Use(CustomRecoveryWithWriter(buffer, handleRecovery))
   157  	router.GET("/recovery", func(_ *Context) {
   158  		panic("Oupps, Houston, we have a problem")
   159  	})
   160  	// RUN
   161  	w := performRequest(router, "GET", "/recovery")
   162  	// TEST
   163  	assert.Equal(t, http.StatusBadRequest, w.Code)
   164  	assert.Contains(t, buffer.String(), "panic recovered")
   165  	assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
   166  	assert.Contains(t, buffer.String(), t.Name())
   167  	assert.NotContains(t, buffer.String(), "GET /recovery")
   168  
   169  	// Debug mode prints the request
   170  	SetMode(DebugMode)
   171  	// RUN
   172  	w = performRequest(router, "GET", "/recovery")
   173  	// TEST
   174  	assert.Equal(t, http.StatusBadRequest, w.Code)
   175  	assert.Contains(t, buffer.String(), "GET /recovery")
   176  
   177  	assert.Equal(t, strings.Repeat("Oupps, Houston, we have a problem", 2), errBuffer.String())
   178  
   179  	SetMode(TestMode)
   180  }
   181  
   182  func TestCustomRecovery(t *testing.T) {
   183  	errBuffer := new(bytes.Buffer)
   184  	buffer := new(bytes.Buffer)
   185  	router := New()
   186  	DefaultErrorWriter = buffer
   187  	handleRecovery := func(c *Context, err interface{}) {
   188  		errBuffer.WriteString(err.(string))
   189  		c.AbortWithStatus(http.StatusBadRequest)
   190  	}
   191  	router.Use(CustomRecovery(handleRecovery))
   192  	router.GET("/recovery", func(_ *Context) {
   193  		panic("Oupps, Houston, we have a problem")
   194  	})
   195  	// RUN
   196  	w := performRequest(router, "GET", "/recovery")
   197  	// TEST
   198  	assert.Equal(t, http.StatusBadRequest, w.Code)
   199  	assert.Contains(t, buffer.String(), "panic recovered")
   200  	assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
   201  	assert.Contains(t, buffer.String(), t.Name())
   202  	assert.NotContains(t, buffer.String(), "GET /recovery")
   203  
   204  	// Debug mode prints the request
   205  	SetMode(DebugMode)
   206  	// RUN
   207  	w = performRequest(router, "GET", "/recovery")
   208  	// TEST
   209  	assert.Equal(t, http.StatusBadRequest, w.Code)
   210  	assert.Contains(t, buffer.String(), "GET /recovery")
   211  
   212  	assert.Equal(t, strings.Repeat("Oupps, Houston, we have a problem", 2), errBuffer.String())
   213  
   214  	SetMode(TestMode)
   215  }
   216  
   217  func TestRecoveryWithWriterWithCustomRecovery(t *testing.T) {
   218  	errBuffer := new(bytes.Buffer)
   219  	buffer := new(bytes.Buffer)
   220  	router := New()
   221  	DefaultErrorWriter = buffer
   222  	handleRecovery := func(c *Context, err interface{}) {
   223  		errBuffer.WriteString(err.(string))
   224  		c.AbortWithStatus(http.StatusBadRequest)
   225  	}
   226  	router.Use(RecoveryWithWriter(DefaultErrorWriter, handleRecovery))
   227  	router.GET("/recovery", func(_ *Context) {
   228  		panic("Oupps, Houston, we have a problem")
   229  	})
   230  	// RUN
   231  	w := performRequest(router, "GET", "/recovery")
   232  	// TEST
   233  	assert.Equal(t, http.StatusBadRequest, w.Code)
   234  	assert.Contains(t, buffer.String(), "panic recovered")
   235  	assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
   236  	assert.Contains(t, buffer.String(), t.Name())
   237  	assert.NotContains(t, buffer.String(), "GET /recovery")
   238  
   239  	// Debug mode prints the request
   240  	SetMode(DebugMode)
   241  	// RUN
   242  	w = performRequest(router, "GET", "/recovery")
   243  	// TEST
   244  	assert.Equal(t, http.StatusBadRequest, w.Code)
   245  	assert.Contains(t, buffer.String(), "GET /recovery")
   246  
   247  	assert.Equal(t, strings.Repeat("Oupps, Houston, we have a problem", 2), errBuffer.String())
   248  
   249  	SetMode(TestMode)
   250  }