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  }