github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/httpcache/httpcache_test.go (about)

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