github.com/sunvim/utils@v0.1.0/linear_ac/linear_ac_test.go (about)

     1  // reference to
     2  // https://github.com/crazybie/linear_ac
     3  package linear_ac
     4  
     5  import (
     6  	"fmt"
     7  	"math/rand"
     8  	"runtime"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  type EnumA int32
    15  
    16  const (
    17  	EnumVal1 EnumA = 1
    18  	EnumVal2 EnumA = 2
    19  )
    20  
    21  type PbItem struct {
    22  	Id      *int
    23  	Price   *int
    24  	Class   *int
    25  	Name    *string
    26  	Active  *bool
    27  	EnumVal *EnumA
    28  }
    29  
    30  type PbData struct {
    31  	Age   *int
    32  	Items []*PbItem
    33  	InUse *PbItem
    34  }
    35  
    36  func Test_GoRoutineId(t *testing.T) {
    37  	id := goRoutineId()
    38  	if id != goRoutineIdSlow() {
    39  		t.Fail()
    40  	}
    41  }
    42  
    43  func Test_LinearAlloc(t *testing.T) {
    44  	ac := BindNew()
    45  	var d *PbData
    46  	ac.New(&d)
    47  	d.Age = ac.Int(11)
    48  
    49  	n := 3
    50  	for i := 0; i < n; i++ {
    51  		var item *PbItem
    52  		ac.New(&item)
    53  		item.Id = ac.Int(i + 1)
    54  		item.Active = ac.Bool(true)
    55  		item.Price = ac.Int(100 + i)
    56  		item.Class = ac.Int(3 + i)
    57  		item.Name = ac.String("name")
    58  
    59  		ac.SliceAppend(&d.Items, item)
    60  	}
    61  
    62  	if *d.Age != 11 {
    63  		t.Errorf("age")
    64  	}
    65  
    66  	if len(d.Items) != int(n) {
    67  		t.Errorf("item")
    68  	}
    69  	for i := 0; i < n; i++ {
    70  		if *d.Items[i].Id != i+1 {
    71  			t.Errorf("item.id")
    72  		}
    73  		if *d.Items[i].Price != i+100 {
    74  			t.Errorf("item.price")
    75  		}
    76  		if *d.Items[i].Class != i+3 {
    77  			t.Errorf("item.class")
    78  		}
    79  	}
    80  	ac.reset()
    81  	ac.Release()
    82  }
    83  
    84  func Test_String(t *testing.T) {
    85  	ac := BindNew()
    86  
    87  	type D struct {
    88  		s [5]*string
    89  	}
    90  	var d *D
    91  	ac.New(&d)
    92  	for i := range d.s {
    93  		d.s[i] = ac.String(fmt.Sprintf("str%v", i))
    94  		runtime.GC()
    95  	}
    96  	for i, p := range d.s {
    97  		if *p != fmt.Sprintf("str%v", i) {
    98  			t.Errorf("elem %v is gced", i)
    99  		}
   100  	}
   101  	ac.Release()
   102  }
   103  
   104  func TestLinearAllocator_NewMap(t *testing.T) {
   105  	ac := BindNew()
   106  
   107  	type D struct {
   108  		m map[int]*int
   109  	}
   110  	data := [10]*D{}
   111  	for i := 0; i < len(data); i++ {
   112  		var d *D
   113  		ac.New(&d)
   114  		ac.NewMap(&d.m)
   115  		d.m[1] = ac.Int(i)
   116  		data[i] = d
   117  		runtime.GC()
   118  	}
   119  	for i, d := range data {
   120  		if *d.m[1] != i {
   121  			t.Fail()
   122  		}
   123  	}
   124  	ac.Release()
   125  }
   126  
   127  func TestLinearAllocator_NewSlice(t *testing.T) {
   128  	DbgMode = true
   129  	ac := BindNew()
   130  	s := make([]*int, 0)
   131  	ac.SliceAppend(&s, ac.Int(2))
   132  	if len(s) != 1 && *s[0] != 2 {
   133  		t.Fail()
   134  	}
   135  
   136  	ac.NewSlice(&s, 0, 32)
   137  	ac.SliceAppend(&s, ac.Int(1))
   138  	if cap(s) != 32 || *s[0] != 1 {
   139  		t.Fail()
   140  	}
   141  
   142  	intSlice := []int{}
   143  	ac.SliceAppend(&intSlice, 11)
   144  	if len(intSlice) != 1 || intSlice[0] != 11 {
   145  		t.Fail()
   146  	}
   147  
   148  	byteSlice := []byte{}
   149  	ac.SliceAppend(&byteSlice, byte(11))
   150  	if len(byteSlice) != 1 || byteSlice[0] != 11 {
   151  		t.Fail()
   152  	}
   153  
   154  	type Data struct {
   155  		d [2]uint64
   156  	}
   157  	structSlice := []Data{}
   158  	d1 := uint64(0xcdcdefefcdcdefdc)
   159  	d2 := uint64(0xcfcdefefcdcfffde)
   160  	ac.SliceAppend(&structSlice, Data{d: [2]uint64{d1, d2}})
   161  	if len(structSlice) != 1 || structSlice[0].d[0] != d1 || structSlice[0].d[1] != d2 {
   162  		t.Fail()
   163  	}
   164  
   165  	f := func() []int {
   166  		var r []int
   167  		ac.NewSlice(&r, 0, 1)
   168  		ac.SliceAppend(&r, 1)
   169  		return r
   170  	}
   171  	r := f()
   172  	if len(r) != 1 {
   173  		t.Errorf("return slice")
   174  	}
   175  
   176  	{
   177  		var s []*PbItem
   178  		ac.SliceAppend(&s, nil)
   179  		if len(s) != 1 || s[0] != nil {
   180  			t.Errorf("nil")
   181  		}
   182  	}
   183  
   184  	{
   185  		s := []int{2, 3, 4}
   186  		r := ac.CopySlice(s).([]int)
   187  		s[0] = 1
   188  		s[1] = 1
   189  		s[2] = 1
   190  		if len(r) != len(s) {
   191  			t.Errorf("copy")
   192  		}
   193  		for i := range s {
   194  			if s[i] == r[i] {
   195  				t.Errorf("copy elem")
   196  			}
   197  		}
   198  	}
   199  
   200  	ac.Release()
   201  }
   202  
   203  func TestLinearAllocator_NewCopy(b *testing.T) {
   204  	ac := BindNew()
   205  	for i := 0; i < 3; i++ {
   206  		d := ac.NewCopy(&PbItem{
   207  			Id:    ac.Int(1 + i),
   208  			Class: ac.Int(2 + i),
   209  			Price: ac.Int(3 + i),
   210  			Name:  ac.String("test"),
   211  		}).(*PbItem)
   212  
   213  		if *d.Id != 1+i {
   214  			b.Fail()
   215  		}
   216  		if *d.Class != 2+i {
   217  			b.Fail()
   218  		}
   219  		if *d.Price != 3+i {
   220  			b.Fail()
   221  		}
   222  		if *d.Name != "test" {
   223  			b.Fail()
   224  		}
   225  	}
   226  	ac.Release()
   227  }
   228  
   229  func TestAllocator_Enum(t *testing.T) {
   230  	ac := BindNew()
   231  	e := EnumVal2
   232  	v := ac.Enum(e).(*EnumA)
   233  	if *v != e {
   234  		t.Fail()
   235  	}
   236  	ac.Release()
   237  }
   238  
   239  func TestBuildInAllocator_All(t *testing.T) {
   240  	ac := buildInAc
   241  	var item *PbItem
   242  	ac.New(&item)
   243  	item.Id = ac.Int(11)
   244  	if *item.Id != 11 {
   245  		t.Fail()
   246  	}
   247  	id2 := 22
   248  	item = ac.NewCopy(&PbItem{Id: &id2}).(*PbItem)
   249  	if *item.Id != 22 {
   250  		t.Fail()
   251  	}
   252  	var s []*PbItem
   253  	ac.NewSlice(&s, 0, 3)
   254  	if cap(s) != 3 || len(s) != 0 {
   255  		t.Fail()
   256  	}
   257  	ac.SliceAppend(&s, item)
   258  	if len(s) != 1 || *s[0].Id != 22 {
   259  		t.Fail()
   260  	}
   261  	var m map[int]string
   262  	ac.NewMap(&m)
   263  	m[1] = "test"
   264  	if m[1] != "test" {
   265  		t.Fail()
   266  	}
   267  	e := EnumVal1
   268  	v := ac.Enum(e).(*EnumA)
   269  	if *v != e {
   270  		t.Fail()
   271  	}
   272  	ac.Release()
   273  }
   274  
   275  func TestBindAc(t *testing.T) {
   276  	useAc := func() *Allocator {
   277  		return Get()
   278  	}
   279  
   280  	wg := sync.WaitGroup{}
   281  	for i := 0; i < 1000; i++ {
   282  		go func() {
   283  			wg.Add(1)
   284  
   285  			ac := BindNew()
   286  			defer ac.Release()
   287  
   288  			time.Sleep(time.Duration(rand.Float32()*1000) * time.Millisecond)
   289  
   290  			if useAc() != ac {
   291  				t.Fail()
   292  			}
   293  			wg.Done()
   294  		}()
   295  	}
   296  	wg.Wait()
   297  }