@@ -4,6 +4,8 @@ package cache
44
55import (
66 "bytes"
7+ "context"
8+ "errors"
79 "fmt"
810 "io"
911 "math"
@@ -21,6 +23,153 @@ import (
2123 "github.com/valyala/fasthttp"
2224)
2325
26+ type failingCacheStorage struct {
27+ data map [string ][]byte
28+ errs map [string ]error
29+ }
30+
31+ func newFailingCacheStorage () * failingCacheStorage {
32+ return & failingCacheStorage {
33+ data : make (map [string ][]byte ),
34+ errs : make (map [string ]error ),
35+ }
36+ }
37+
38+ func (s * failingCacheStorage ) GetWithContext (_ context.Context , key string ) ([]byte , error ) {
39+ if err , ok := s .errs ["get|" + key ]; ok && err != nil {
40+ return nil , err
41+ }
42+ if val , ok := s .data [key ]; ok {
43+ return append ([]byte (nil ), val ... ), nil
44+ }
45+ return nil , nil
46+ }
47+
48+ func (s * failingCacheStorage ) Get (key string ) ([]byte , error ) {
49+ return s .GetWithContext (context .Background (), key )
50+ }
51+
52+ func (s * failingCacheStorage ) SetWithContext (_ context.Context , key string , val []byte , _ time.Duration ) error {
53+ if err , ok := s .errs ["set|" + key ]; ok && err != nil {
54+ return err
55+ }
56+ s .data [key ] = append ([]byte (nil ), val ... )
57+ return nil
58+ }
59+
60+ func (s * failingCacheStorage ) Set (key string , val []byte , exp time.Duration ) error {
61+ return s .SetWithContext (context .Background (), key , val , exp )
62+ }
63+
64+ func (s * failingCacheStorage ) DeleteWithContext (_ context.Context , key string ) error {
65+ if err , ok := s .errs ["del|" + key ]; ok && err != nil {
66+ return err
67+ }
68+ delete (s .data , key )
69+ return nil
70+ }
71+
72+ func (s * failingCacheStorage ) Delete (key string ) error {
73+ return s .DeleteWithContext (context .Background (), key )
74+ }
75+
76+ func (s * failingCacheStorage ) ResetWithContext (context.Context ) error {
77+ s .data = make (map [string ][]byte )
78+ s .errs = make (map [string ]error )
79+ return nil
80+ }
81+
82+ func (s * failingCacheStorage ) Reset () error {
83+ return s .ResetWithContext (context .Background ())
84+ }
85+
86+ func (* failingCacheStorage ) Close () error { return nil }
87+
88+ func TestCacheStorageGetError (t * testing.T ) {
89+ t .Parallel ()
90+
91+ storage := newFailingCacheStorage ()
92+ storage .errs ["get|/_GET" ] = errors .New ("boom" )
93+
94+ var captured error
95+ app := fiber .New (fiber.Config {
96+ ErrorHandler : func (c fiber.Ctx , err error ) error {
97+ captured = err
98+ return c .Status (fiber .StatusInternalServerError ).SendString ("storage failure" )
99+ },
100+ })
101+
102+ app .Use (New (Config {Storage : storage , Expiration : time .Second }))
103+ app .Get ("/" , func (c fiber.Ctx ) error {
104+ return c .SendString ("ok" )
105+ })
106+
107+ resp , err := app .Test (httptest .NewRequest (fiber .MethodGet , "/" , nil ))
108+ require .NoError (t , err )
109+ require .Equal (t , fiber .StatusInternalServerError , resp .StatusCode )
110+ require .Error (t , captured )
111+ require .ErrorContains (t , captured , "cache: failed to get key" )
112+ }
113+
114+ func TestCacheStorageSetError (t * testing.T ) {
115+ t .Parallel ()
116+
117+ storage := newFailingCacheStorage ()
118+ storage .errs ["set|/_GET_body" ] = errors .New ("boom" )
119+
120+ var captured error
121+ app := fiber .New (fiber.Config {
122+ ErrorHandler : func (c fiber.Ctx , err error ) error {
123+ captured = err
124+ return c .Status (fiber .StatusInternalServerError ).SendString ("storage failure" )
125+ },
126+ })
127+
128+ app .Use (New (Config {Storage : storage , Expiration : time .Second }))
129+ app .Get ("/" , func (c fiber.Ctx ) error {
130+ return c .SendString ("ok" )
131+ })
132+
133+ resp , err := app .Test (httptest .NewRequest (fiber .MethodGet , "/" , nil ))
134+ require .NoError (t , err )
135+ require .Equal (t , fiber .StatusInternalServerError , resp .StatusCode )
136+ require .Error (t , captured )
137+ require .ErrorContains (t , captured , "cache: failed to store raw key" )
138+ }
139+
140+ func TestCacheStorageDeleteError (t * testing.T ) {
141+ t .Parallel ()
142+
143+ storage := newFailingCacheStorage ()
144+ storage .errs ["del|/_GET" ] = errors .New ("boom" )
145+
146+ // Use an obviously expired timestamp without relying on time-based conversions
147+ expired := & item {exp : 1 }
148+ raw , err := expired .MarshalMsg (nil )
149+ require .NoError (t , err )
150+
151+ storage .data ["/_GET" ] = raw
152+
153+ var captured error
154+ app := fiber .New (fiber.Config {
155+ ErrorHandler : func (c fiber.Ctx , err error ) error {
156+ captured = err
157+ return c .Status (fiber .StatusInternalServerError ).SendString ("storage failure" )
158+ },
159+ })
160+
161+ app .Use (New (Config {Storage : storage , Expiration : time .Second }))
162+ app .Get ("/" , func (c fiber.Ctx ) error {
163+ return c .SendString ("ok" )
164+ })
165+
166+ resp , err := app .Test (httptest .NewRequest (fiber .MethodGet , "/" , nil ))
167+ require .NoError (t , err )
168+ require .Equal (t , fiber .StatusInternalServerError , resp .StatusCode )
169+ require .Error (t , captured )
170+ require .ErrorContains (t , captured , "cache: failed to delete expired key" )
171+ }
172+
24173func Test_Cache_CacheControl (t * testing.T ) {
25174 t .Parallel ()
26175
0 commit comments