github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/asyncbuffer/buffer_test.go (about)

     1  package asyncbuffer
     2  
     3  import (
     4  	"bytes"
     5  	"math/rand"
     6  	"runtime"
     7  	"strconv"
     8  	"sync"
     9  	"sync/atomic"
    10  	_ "syscall"
    11  	"testing"
    12  	"time"
    13  	"unsafe"
    14  )
    15  
    16  var itemMap map[string]int = map[string]int{}
    17  
    18  //var gItemMap sync.Map
    19  var gCounter uint64
    20  
    21  func (m *DemoBuffer) BatchDo(data [][]byte) {
    22  	//println("bufferLen:", len(data))
    23  	bufferData := ""
    24  	for _, item := range data {
    25  		//println("getSendDataFrom item:", *(*string)(unsafe.Pointer(&item)))
    26  		//time.Sleep(300 * time.Millisecond)
    27  
    28  		//_, ok := gItemMap.Load(*(*string)(unsafe.Pointer(&item)))
    29  		_, ok := itemMap[*(*string)(unsafe.Pointer(&item))]
    30  		if !ok {
    31  			atomic.AddUint64(&gCounter, 1)
    32  			//gItemMap.Store(*(*string)(unsafe.Pointer(&item)), 1)
    33  			itemMap[*(*string)(unsafe.Pointer(&item))] = 1
    34  			//println("lenItemMap:", len(itemMap))
    35  		} else {
    36  			println("repeat item:", *(*string)(unsafe.Pointer(&item)))
    37  		}
    38  
    39  		bufferData += *(*string)(unsafe.Pointer(&item)) + "\t"
    40  		if *(*string)(unsafe.Pointer(&item)) == "10" {
    41  			//panic("panic:" + string(item))
    42  		}
    43  	}
    44  
    45  	//println("bufferData:", bufferData)
    46  }
    47  
    48  func (m *DemoBuffer) FormatInput() (err error, bytes []byte) {
    49  	return nil, []byte(m.Name)
    50  }
    51  
    52  func TestMain(m *testing.M) {
    53  	m.Run()
    54  }
    55  
    56  func TestFlushOne(t *testing.T) {
    57  	InitInstancesByConf()
    58  	time.Sleep(3 * time.Second)
    59  
    60  	type InputCase struct {
    61  		BufferName string
    62  	}
    63  	inputCases := []InputCase{{BufferName: "default"}, {BufferName: "default"}, {BufferName: "nmq_live_user"}}
    64  
    65  	for _, inputCase := range inputCases {
    66  		FlushOne(inputCase.BufferName)
    67  		time.Sleep(3 * time.Second)
    68  	}
    69  }
    70  
    71  func TestSendOneCh(t *testing.T) {
    72  	InitInstancesByConf()
    73  	time.Sleep(3 * time.Second)
    74  
    75  	type InputCase struct {
    76  		BufferName string
    77  		ChName     string
    78  		Data       IBuffer
    79  	}
    80  	inputCases := []InputCase{
    81  		{
    82  			BufferName: "default",
    83  			ChName:     "default",
    84  			Data:       &DemoBuffer{Name: "testDefault1"},
    85  		},
    86  		{
    87  			BufferName: "default",
    88  			ChName:     "default",
    89  			Data:       &DemoBuffer{Name: "testDefault2"},
    90  		},
    91  		{
    92  			BufferName: "nmq_live_user",
    93  			ChName:     "nmq",
    94  			Data:       &DemoBuffer{Name: "testUser1"},
    95  		},
    96  		{
    97  			BufferName: "nmq_live_user",
    98  			ChName:     "nmq",
    99  			Data:       &DemoBuffer{Name: "testUser2"},
   100  		},
   101  	}
   102  
   103  	for _, inputCase := range inputCases {
   104  		err := SendOneCh(inputCase.BufferName, inputCase.ChName, inputCase.Data)
   105  		if err != nil {
   106  			t.Errorf("SendOneCh bufferName: %s chName: %s data: %v err: %s", inputCase.BufferName, inputCase.ChName, inputCase.Data, err.Error())
   107  		}
   108  	}
   109  
   110  	FlushAll()
   111  
   112  	ch := make(chan int)
   113  	ch <- 1
   114  
   115  }
   116  
   117  func TestMultiWorkerSendOneCh(t *testing.T) {
   118  	InitInstancesByConf()
   119  	//time.Sleep(3 * time.Second)
   120  
   121  	var start time.Time
   122  	var end time.Time
   123  
   124  	type InputCase struct {
   125  		BufferName string
   126  		ChName     string
   127  		Data       IBuffer
   128  	}
   129  	start = time.Now()
   130  	//exitCh := make(chan int)
   131  
   132  run:
   133  	// N+1 goroutine  send D (N+1 * D)
   134  	var wg sync.WaitGroup
   135  	N := 9
   136  	D := 303
   137  	for i := 1; i <= N*D+1; i += D {
   138  		wg.Add(1)
   139  		go func(uid int) {
   140  			opCn := 0
   141  			for {
   142  				if opCn >= 3 {
   143  					end = time.Now()
   144  					// 执行时间 单位:微秒
   145  					_ = end.Sub(start).Nanoseconds() / 1e3
   146  					//println("gid:", getGID())
   147  					//println("pid", syscall.Getpid())
   148  					break
   149  				}
   150  				opCn += 1
   151  				testCases := []InputCase{}
   152  				for i := 1; i <= 101; i++ {
   153  					strUid := strconv.Itoa(uid)
   154  					testCase := InputCase{
   155  						BufferName: "default",
   156  						ChName:     "default",
   157  						Data:       &DemoBuffer{Name: "" + strUid},
   158  					}
   159  					testCases = append(testCases, testCase)
   160  					uid++
   161  				}
   162  				r := rand.New(rand.NewSource(time.Now().UnixNano()))
   163  				randVal := r.Intn(10)
   164  				//println("sleep", randVal, "flush")
   165  				time.Sleep(time.Duration(randVal) * time.Second)
   166  				//FlushOne("default")
   167  
   168  				for _, testCase := range testCases {
   169  					err := SendOneCh(testCase.BufferName, testCase.ChName, testCase.Data)
   170  					if err != nil {
   171  						t.Errorf("SendOneCh bufferName: %s chName: %s data: %v err: %s", testCase.BufferName, testCase.ChName, testCase.Data, err.Error())
   172  					}
   173  				}
   174  				//time.Sleep(200 * time.Millisecond)
   175  			}
   176  			//println("flushOne")
   177  			FlushOne("default")
   178  			time.Sleep(200 * time.Millisecond)
   179  			wg.Done()
   180  		}(i)
   181  	}
   182  	wg.Wait()
   183  
   184  	//println("flushAll")
   185  	//FlushAll()
   186  	//time.Sleep(200 * time.Millisecond)
   187  
   188  	cn := 0
   189  	/*
   190  		for i := 1; i <= (N+1) * D; i++ {
   191  			if _, ok := gItemMap.Load(strconv.Itoa(i)); !ok {
   192  				println("un send---->", i)
   193  			} else {
   194  				cn++
   195  			}
   196  		}
   197  	*/
   198  
   199  	for i := 1; i <= (N+1)*D; i++ {
   200  		if _, ok := itemMap[strconv.Itoa(i)]; !ok {
   201  			println("un send---->", i)
   202  		}
   203  	}
   204  	cn = len(itemMap)
   205  
   206  	println("cn:", cn)
   207  
   208  	println("counter:", gCounter)
   209  	println("buffCounter:", gBufferSendDataInstances["default"].BufferDayCounter)
   210  	println("bufferIndex:", gBufferSendDataInstances["default"].BufferIndex)
   211  	for j := int64(0); j < gBufferSendDataInstances["default"].BufferIndex; j++ {
   212  		println("unSendBufferData:", string(gBufferSendDataInstances["default"].BufferData[j]))
   213  	}
   214  
   215  	time.Sleep(5000 * time.Millisecond)
   216  	println("bufferIndex:", gBufferSendDataInstances["default"].BufferIndex)
   217  
   218  	atomic.StoreUint64(&gCounter, 0)
   219  	itemMap = map[string]int{}
   220  	goto run
   221  
   222  	ch := make(chan int)
   223  	ch <- 1
   224  	//time.Sleep(10000 * time.Millisecond)
   225  
   226  }
   227  
   228  func getGID() uint64 {
   229  	b := make([]byte, 64)
   230  	b = b[:runtime.Stack(b, false)]
   231  	b = bytes.TrimPrefix(b, []byte("goroutine "))
   232  	b = b[:bytes.IndexByte(b, ' ')]
   233  	n, _ := strconv.ParseUint(string(b), 10, 64)
   234  	return n
   235  }