code.gitea.io/gitea@v1.19.3/modules/httpcache/httpcache_test.go (about)

     1  // Copyright 2021 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package httpcache
     5  
     6  import (
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"os"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  type mockFileInfo struct{}
    18  
    19  func (m mockFileInfo) Name() string       { return "gitea.test" }
    20  func (m mockFileInfo) Size() int64        { return int64(10) }
    21  func (m mockFileInfo) Mode() os.FileMode  { return os.ModePerm }
    22  func (m mockFileInfo) ModTime() time.Time { return time.Time{} }
    23  func (m mockFileInfo) IsDir() bool        { return false }
    24  func (m mockFileInfo) Sys() interface{}   { return nil }
    25  
    26  func countFormalHeaders(h http.Header) (c int) {
    27  	for k := range h {
    28  		// ignore our headers for internal usage
    29  		if strings.HasPrefix(k, "X-Gitea-") {
    30  			continue
    31  		}
    32  		c++
    33  	}
    34  	return c
    35  }
    36  
    37  func TestHandleFileETagCache(t *testing.T) {
    38  	fi := mockFileInfo{}
    39  	etag := `"MTBnaXRlYS50ZXN0TW9uLCAwMSBKYW4gMDAwMSAwMDowMDowMCBHTVQ="`
    40  
    41  	t.Run("No_If-None-Match", func(t *testing.T) {
    42  		req := &http.Request{Header: make(http.Header)}
    43  		w := httptest.NewRecorder()
    44  
    45  		handled := HandleFileETagCache(req, w, fi)
    46  
    47  		assert.False(t, handled)
    48  		assert.Equal(t, 2, countFormalHeaders(w.Header()))
    49  		assert.Contains(t, w.Header(), "Cache-Control")
    50  		assert.Contains(t, w.Header(), "Etag")
    51  		assert.Equal(t, etag, w.Header().Get("Etag"))
    52  	})
    53  	t.Run("Wrong_If-None-Match", func(t *testing.T) {
    54  		req := &http.Request{Header: make(http.Header)}
    55  		w := httptest.NewRecorder()
    56  
    57  		req.Header.Set("If-None-Match", `"wrong etag"`)
    58  
    59  		handled := HandleFileETagCache(req, w, fi)
    60  
    61  		assert.False(t, handled)
    62  		assert.Equal(t, 2, countFormalHeaders(w.Header()))
    63  		assert.Contains(t, w.Header(), "Cache-Control")
    64  		assert.Contains(t, w.Header(), "Etag")
    65  		assert.Equal(t, etag, w.Header().Get("Etag"))
    66  	})
    67  	t.Run("Correct_If-None-Match", func(t *testing.T) {
    68  		req := &http.Request{Header: make(http.Header)}
    69  		w := httptest.NewRecorder()
    70  
    71  		req.Header.Set("If-None-Match", etag)
    72  
    73  		handled := HandleFileETagCache(req, w, fi)
    74  
    75  		assert.True(t, handled)
    76  		assert.Equal(t, 1, countFormalHeaders(w.Header()))
    77  		assert.Contains(t, w.Header(), "Etag")
    78  		assert.Equal(t, etag, w.Header().Get("Etag"))
    79  		assert.Equal(t, http.StatusNotModified, w.Code)
    80  	})
    81  }
    82  
    83  func TestHandleGenericETagCache(t *testing.T) {
    84  	etag := `"test"`
    85  
    86  	t.Run("No_If-None-Match", func(t *testing.T) {
    87  		req := &http.Request{Header: make(http.Header)}
    88  		w := httptest.NewRecorder()
    89  
    90  		handled := HandleGenericETagCache(req, w, etag)
    91  
    92  		assert.False(t, handled)
    93  		assert.Equal(t, 2, countFormalHeaders(w.Header()))
    94  		assert.Contains(t, w.Header(), "Cache-Control")
    95  		assert.Contains(t, w.Header(), "Etag")
    96  		assert.Equal(t, etag, w.Header().Get("Etag"))
    97  	})
    98  	t.Run("Wrong_If-None-Match", func(t *testing.T) {
    99  		req := &http.Request{Header: make(http.Header)}
   100  		w := httptest.NewRecorder()
   101  
   102  		req.Header.Set("If-None-Match", `"wrong etag"`)
   103  
   104  		handled := HandleGenericETagCache(req, w, etag)
   105  
   106  		assert.False(t, handled)
   107  		assert.Equal(t, 2, countFormalHeaders(w.Header()))
   108  		assert.Contains(t, w.Header(), "Cache-Control")
   109  		assert.Contains(t, w.Header(), "Etag")
   110  		assert.Equal(t, etag, w.Header().Get("Etag"))
   111  	})
   112  	t.Run("Correct_If-None-Match", func(t *testing.T) {
   113  		req := &http.Request{Header: make(http.Header)}
   114  		w := httptest.NewRecorder()
   115  
   116  		req.Header.Set("If-None-Match", etag)
   117  
   118  		handled := HandleGenericETagCache(req, w, etag)
   119  
   120  		assert.True(t, handled)
   121  		assert.Equal(t, 1, countFormalHeaders(w.Header()))
   122  		assert.Contains(t, w.Header(), "Etag")
   123  		assert.Equal(t, etag, w.Header().Get("Etag"))
   124  		assert.Equal(t, http.StatusNotModified, w.Code)
   125  	})
   126  	t.Run("Multiple_Wrong_If-None-Match", func(t *testing.T) {
   127  		req := &http.Request{Header: make(http.Header)}
   128  		w := httptest.NewRecorder()
   129  
   130  		req.Header.Set("If-None-Match", `"wrong etag", "wrong etag "`)
   131  
   132  		handled := HandleGenericETagCache(req, w, etag)
   133  
   134  		assert.False(t, handled)
   135  		assert.Equal(t, 2, countFormalHeaders(w.Header()))
   136  		assert.Contains(t, w.Header(), "Cache-Control")
   137  		assert.Contains(t, w.Header(), "Etag")
   138  		assert.Equal(t, etag, w.Header().Get("Etag"))
   139  	})
   140  	t.Run("Multiple_Correct_If-None-Match", func(t *testing.T) {
   141  		req := &http.Request{Header: make(http.Header)}
   142  		w := httptest.NewRecorder()
   143  
   144  		req.Header.Set("If-None-Match", `"wrong etag", `+etag)
   145  
   146  		handled := HandleGenericETagCache(req, w, etag)
   147  
   148  		assert.True(t, handled)
   149  		assert.Equal(t, 1, countFormalHeaders(w.Header()))
   150  		assert.Contains(t, w.Header(), "Etag")
   151  		assert.Equal(t, etag, w.Header().Get("Etag"))
   152  		assert.Equal(t, http.StatusNotModified, w.Code)
   153  	})
   154  }