github.com/qiniu/go-sdk/v7@v7.27.0/internal/uplog/uplog_buffer_test.go (about) 1 //go:build unit 2 // +build unit 3 4 package uplog 5 6 import ( 7 "bytes" 8 "compress/gzip" 9 "crypto/md5" 10 "io" 11 "log" 12 "math/rand" 13 "net/http" 14 "net/http/httptest" 15 "os" 16 "path/filepath" 17 "strings" 18 "sync" 19 "sync/atomic" 20 "testing" 21 "time" 22 ) 23 24 var testLock sync.Mutex 25 26 func TestUplogWriteMemoryBufferToFileBuffer(t *testing.T) { 27 testLock.Lock() 28 defer testLock.Unlock() 29 30 tmpDir, err := os.MkdirTemp("", "test-uplog-*") 31 if err != nil { 32 t.Fatal(err) 33 } 34 defer os.RemoveAll(tmpDir) 35 36 defer func() { 37 if err := FlushBuffer(); err != nil { 38 t.Fatal(err) 39 } 40 }() 41 42 SetUplogFileBufferDirPath(tmpDir) 43 defer SetUplogFileBufferDirPath("") 44 45 DisableUplog() 46 defer EnableUplog() 47 48 uplogBuffer := bytes.NewBuffer(make([]byte, 0, 4*1024)) 49 n, err := io.CopyN(uplogBuffer, rand.New(rand.NewSource(time.Now().UnixNano())), 1024) 50 if err != nil { 51 t.Fatal(err) 52 } else if n != 1024 { 53 t.Fatalf("unexpected n: %d", n) 54 } 55 56 writeMemoryBufferToFileBuffer(uplogBuffer.Bytes()) 57 uplogBuffer.Reset() 58 59 n, err = io.CopyN(uplogBuffer, rand.New(rand.NewSource(time.Now().UnixNano())), 1024) 60 if err != nil { 61 t.Fatal(err) 62 } else if n != 1024 { 63 t.Fatalf("unexpected n: %d", n) 64 } 65 66 writeMemoryBufferToFileBuffer(uplogBuffer.Bytes()) 67 uplogBuffer.Reset() 68 69 fi, err := os.Stat(filepath.Join(tmpDir, UPLOG_FILE_BUFFER_NAME)) 70 if err != nil { 71 t.Fatal(err) 72 } else if fi.Size() == 0 { 73 t.Fatalf("unexpected fi.Size(): %d", fi.Size()) 74 } 75 } 76 77 func TestUplogArchiveFileBuffer(t *testing.T) { 78 testLock.Lock() 79 defer testLock.Unlock() 80 81 tmpDir, err := os.MkdirTemp("", "test-uplog-*") 82 if err != nil { 83 t.Fatal(err) 84 } 85 defer os.RemoveAll(tmpDir) 86 87 defer func() { 88 if err := FlushBuffer(); err != nil { 89 t.Fatal(err) 90 } 91 }() 92 93 var called int32 94 md5HasherServer := md5.New() 95 httpServerMux := http.NewServeMux() 96 httpServerMux.Handle("/log/4", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 97 if r.Method != http.MethodPost { 98 t.Fatalf("Unexpected method: %s", r.Method) 99 } 100 if r.URL.Query().Get("compressed") != "gzip" { 101 t.Fatalf("Unexpected compressed: %s", r.URL.Query().Get("compressed")) 102 } 103 if r.Header.Get("Authorization") != "UpToken fakeuptoken" { 104 t.Fatalf("Unexpected Authorization: %s", r.Header.Get("Authorization")) 105 } 106 if atomic.AddInt32(&called, 1) > 1 { 107 if r.Header.Get(X_LOG_CLIENT_ID) != "fake-x-log-client-id" { 108 t.Fatalf("Unexpected X-Log-Client-Id: %s", r.Header.Get("X_LOG_CLIENT_ID")) 109 } 110 } 111 w.Header().Add(X_LOG_CLIENT_ID, "fake-x-log-client-id") 112 uncompressedBody, err := gzip.NewReader(r.Body) 113 if err != nil { 114 log.Fatal(err) 115 } 116 if _, err = io.Copy(md5HasherServer, uncompressedBody); err != nil { 117 log.Fatal(err) 118 } 119 })) 120 httpServer := httptest.NewServer(httpServerMux) 121 defer httpServer.Close() 122 123 SetUplogUrl(httpServer.URL) 124 defer SetUplogUrl("") 125 126 getUpToken = func() (string, error) { return "fakeuptoken", nil } 127 defer func() { getUpToken = nil }() 128 129 SetUplogFileBufferDirPath(tmpDir) 130 defer SetUplogFileBufferDirPath("") 131 132 DisableUplog() 133 defer EnableUplog() 134 135 originalUplogFileBufferThreshold := uplogFileBufferThreshold 136 uplogFileBufferThreshold = 24 * 1024 137 defer func() { 138 uplogFileBufferThreshold = originalUplogFileBufferThreshold 139 }() 140 141 uplogBuffer := bytes.NewBuffer(make([]byte, 0, 4*1024)) 142 md5HasherClient := md5.New() 143 r := io.TeeReader(rand.New(rand.NewSource(time.Now().UnixNano())), md5HasherClient) 144 145 for i := 0; i < 4*24; i++ { 146 n, err := io.CopyN(uplogBuffer, r, 1024) 147 if err != nil { 148 t.Fatal(err) 149 } else if n != 1024 { 150 t.Fatalf("unexpected n: %d", n) 151 } 152 153 writeMemoryBufferToFileBuffer(uplogBuffer.Bytes()) 154 uplogBuffer.Reset() 155 time.Sleep(10 * time.Nanosecond) 156 } 157 tryToArchiveFileBuffer(true) 158 time.Sleep(100 * time.Millisecond) 159 c := atomic.LoadInt32(&called) 160 if c == 0 { 161 t.Fatal("unexpected upload count") 162 } 163 if !bytes.Equal(md5HasherClient.Sum(nil), md5HasherServer.Sum(nil)) { 164 t.Fatal("unexpected request body") 165 } 166 entries, err := os.ReadDir(tmpDir) 167 if err != nil { 168 t.Fatal(err) 169 } 170 if len(entries) != 2 && len(entries) != 3 { 171 t.Fatalf("unexpected uplog buffer files count") 172 } 173 for _, entry := range entries { 174 if !strings.HasSuffix(entry.Name(), ".lock") && entry.Name() != UPLOG_FILE_BUFFER_NAME { 175 t.Fatalf("unexpected uplog buffer file: %s", entry.Name()) 176 } 177 } 178 } 179 180 func TestUplogArchiveFileBufferFailed(t *testing.T) { 181 testLock.Lock() 182 defer testLock.Unlock() 183 184 tmpDir, err := os.MkdirTemp("", "test-uplog-*") 185 if err != nil { 186 t.Fatal(err) 187 } 188 defer os.RemoveAll(tmpDir) 189 190 defer func() { 191 if err := FlushBuffer(); err != nil { 192 t.Fatal(err) 193 } 194 }() 195 196 var called int32 197 httpServerMux := http.NewServeMux() 198 httpServerMux.Handle("/log/4", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 199 if r.Method != http.MethodPost { 200 t.Fatalf("Unexpected method: %s", r.Method) 201 } 202 if r.URL.Query().Get("compressed") != "gzip" { 203 t.Fatalf("Unexpected compressed: %s", r.URL.Query().Get("compressed")) 204 } 205 if r.Header.Get("Authorization") != "UpToken fakeuptoken" { 206 t.Fatalf("Unexpected Authorization: %s", r.Header.Get("Authorization")) 207 } 208 if atomic.AddInt32(&called, 1) > 1 { 209 if r.Header.Get(X_LOG_CLIENT_ID) != "fake-x-log-client-id" { 210 t.Fatalf("Unexpected X-Log-Client-Id: %s", r.Header.Get("X_LOG_CLIENT_ID")) 211 } 212 } 213 w.Header().Add(X_LOG_CLIENT_ID, "fake-x-log-client-id") 214 w.WriteHeader(http.StatusInternalServerError) 215 })) 216 httpServer := httptest.NewServer(httpServerMux) 217 defer httpServer.Close() 218 219 SetUplogUrl(httpServer.URL) 220 defer SetUplogUrl("") 221 222 getUpToken = func() (string, error) { return "fakeuptoken", nil } 223 defer func() { getUpToken = nil }() 224 225 SetUplogFileBufferDirPath(tmpDir) 226 defer SetUplogFileBufferDirPath("") 227 228 DisableUplog() 229 defer EnableUplog() 230 231 originalUplogMaxStorageBytes := GetUplogMaxStorageBytes() 232 SetUplogMaxStorageBytes(48 * 1024) 233 defer SetUplogMaxStorageBytes(originalUplogMaxStorageBytes) 234 235 originalUplogFileBufferThreshold := uplogFileBufferThreshold 236 uplogFileBufferThreshold = 24 * 1024 237 defer func() { 238 uplogFileBufferThreshold = originalUplogFileBufferThreshold 239 }() 240 241 uplogBuffer := bytes.NewBuffer(make([]byte, 0, 4*1024)) 242 r := rand.New(rand.NewSource(time.Now().UnixNano())) 243 244 for i := 0; i < 4*24; i++ { 245 n, err := io.CopyN(uplogBuffer, r, 1024) 246 if err != nil { 247 t.Fatal(err) 248 } else if n != 1024 { 249 t.Fatalf("unexpected n: %d", n) 250 } 251 252 writeMemoryBufferToFileBuffer(uplogBuffer.Bytes()) 253 uplogBuffer.Reset() 254 time.Sleep(10 * time.Nanosecond) 255 } 256 tryToArchiveFileBuffer(true) 257 time.Sleep(100 * time.Millisecond) 258 c := atomic.LoadInt32(&called) 259 if c == 0 { 260 t.Fatal("unexpected upload count") 261 } 262 263 entries, err := os.ReadDir(tmpDir) 264 if err != nil { 265 t.Fatal(err) 266 } 267 totalSize := uint64(0) 268 for _, entry := range entries { 269 info, err := entry.Info() 270 if err != nil { 271 t.Fatal(err) 272 } 273 totalSize += uint64(info.Size()) 274 } 275 if totalSize > 48*1024 { 276 t.Fatalf("unexpected uplog buffer file size: %d", totalSize) 277 } 278 }