123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- package go_int32_handle
- import (
- "fmt"
- "math/rand"
- "runtime"
- "sync"
- "testing"
- )
- func TestFunc1(t *testing.T) {
- hm := New[string]()
- h1 := testUtilAlloc(hm, t, "hello")
- h2 := testUtilAlloc(hm, t, "world")
- testUtilGet(hm, t, h1, "hello")
- testUtilGet(hm, t, h2, "world")
- testUtilRelease(hm, t, h1, "hello")
- h3 := testUtilAlloc(hm, t, "gensoukyo")
- testUtilGet(hm, t, h3, "gensoukyo")
- testUtilRelease(hm, t, h2, "world")
- testUtilRelease(hm, t, h3, "gensoukyo")
- h4 := testUtilAlloc(hm, t, "satori")
- h5 := testUtilAlloc(hm, t, "koishi")
- h6 := testUtilAlloc(hm, t, "cirno")
- testUtilGet(hm, t, h4, "satori")
- testUtilGet(hm, t, h5, "koishi")
- testUtilGet(hm, t, h6, "cirno")
- }
- func TestFunc2(t *testing.T) {
- hm := NewWithRange[string](0, 32)
- var i int32
- for i = 0; i < 31; i++ {
- testUtilAlloc(hm, t, fmt.Sprintf("val-%d", i))
- }
- for i = 0; i < 31; i++ {
- testUtilGet(hm, t, i+1, fmt.Sprintf("val-%d", i))
- }
- testUtilAllocOverflow(hm, t, "val-32")
- testUtilRelease(hm, t, 15, "val-14")
- hr := testUtilAlloc(hm, t, "val-xr-14")
- if hr != 15 {
- t.Fatalf("allocate behavior mismatch: expected 15, got %d", hr)
- }
- testUtilGet(hm, t, hr, "val-xr-14")
- }
- func TestFunc3(t *testing.T) {
- tryCount := 65536
- hm := New[string]()
- tlist := make([]struct {
- h int32
- v string
- }, 0, tryCount)
- t.Log("==== Do Random Alloc and Release ====")
- for i := 0; i < tryCount; i++ {
- ri := rand.Int31()
- rk := rand.Intn(10)
- if rk == 0 && len(tlist) > 0 {
- sel := rand.Intn(len(tlist))
- testUtilReleaseSilent(hm, t, tlist[sel].h, tlist[sel].v)
- tlist = append(tlist[:sel], tlist[sel+1:]...)
- } else {
- v := fmt.Sprintf("val-test-%d", ri)
- h := testUtilAllocSilent(hm, t, v)
- tlist = append(tlist, struct {
- h int32
- v string
- }{h: h, v: v})
- }
- }
- t.Log("==== Do Verification ====")
- for i := 0; i < len(tlist); i++ {
- testUtilGetSilent(hm, t, tlist[i].h, tlist[i].v)
- }
- }
- func TestFunc4(t *testing.T) {
- eachRoutineTryCount := 65536
- routineCount := runtime.NumCPU()
- hm := New[string]()
- wg := sync.WaitGroup{}
- wg.Add(routineCount)
- t.Logf("routineCount: %d", routineCount)
- t.Log("==== Do Parallel Random Alloc and Release Test ====")
- for i := 0; i < routineCount; i++ {
- go func() {
- testUtilDoRandom(hm, eachRoutineTryCount)
- wg.Done()
- }()
- }
- wg.Wait()
- t.Log("==== Done ====")
- }
- func BenchmarkAlloc(b *testing.B) {
- hm := New[string]()
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- _, _ = hm.AllocateAndPut("hello")
- }
- })
- }
- func BenchmarkGet(b *testing.B) {
- maxCount := 65536
- hm := New[string]()
- for i := 0; i < maxCount; i++ {
- _, _ = hm.AllocateAndPut(fmt.Sprintf("val-%d", i))
- }
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- _, _ = hm.Get(int32(rand.Intn(maxCount)))
- }
- })
- }
- func BenchmarkComprehensive(b *testing.B) {
- hm := New[string]()
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- op := rand.Intn(3)
- switch op {
- case 0:
- _, _ = hm.AllocateAndPut("hello")
- case 1:
- if hm.Count() <= 0 {
- _, _ = hm.AllocateAndPut("hello")
- } else {
- _, _ = hm.Get(int32(rand.Intn(hm.Count())))
- }
- case 2:
- if hm.Count() <= 0 {
- _, _ = hm.AllocateAndPut("hello")
- } else {
- hm.ReleaseSilently(int32(rand.Intn(hm.Count())))
- }
- }
- }
- })
- }
- func testUtilDoRandom(hm *HandleManager[string], tryCount int) {
- tlist := make([]struct {
- h int32
- v string
- }, 0, tryCount)
- for i := 0; i < tryCount; i++ {
- ri := rand.Int31()
- rk := rand.Intn(10)
- if rk == 0 && len(tlist) > 0 {
- sel := rand.Intn(len(tlist))
- h := tlist[sel].h
- v := tlist[sel].v
- releasedVal, ok := hm.Release(h)
- if !ok {
- panic(fmt.Errorf("failed to release handle %d: not found", h))
- }
- if releasedVal != v {
- panic(fmt.Errorf("release handle %d result mismatched: expected %s, got %s", h, v, releasedVal))
- }
- tlist = append(tlist[:sel], tlist[sel+1:]...)
- } else {
- v := fmt.Sprintf("val-test-%d", ri)
- h, err := hm.AllocateAndPut(v)
- if err != nil {
- panic(fmt.Errorf("failed to allocate handle: %v", err))
- }
- tlist = append(tlist, struct {
- h int32
- v string
- }{h: h, v: v})
- }
- }
- for i := 0; i < len(tlist); i++ {
- h := tlist[i].h
- v := tlist[i].v
- vr, ok := hm.Get(h)
- if !ok {
- panic(fmt.Errorf("failed to get handle %d: not found", h))
- return
- }
- if vr != v {
- panic(fmt.Errorf("get handle %d result mismatched: expected %s, got %s", h, v, vr))
- return
- }
- }
- }
- func testUtilAlloc(hm *HandleManager[string], t *testing.T, val string) int32 {
- h, err := hm.AllocateAndPut(val)
- if err != nil {
- t.Fatalf("failed to allocate handle: %v", err)
- return 0
- }
- t.Logf("allocated handle %d", h)
- return h
- }
- func testUtilAllocSilent(hm *HandleManager[string], t *testing.T, val string) int32 {
- h, err := hm.AllocateAndPut(val)
- if err != nil {
- t.Fatalf("failed to allocate handle: %v", err)
- return 0
- }
- return h
- }
- func testUtilAllocOverflow(hm *HandleManager[string], t *testing.T, val string) {
- _, err := hm.AllocateAndPut(val)
- if err == ErrHandleExceedMax {
- t.Log("allocated a overflowed handle got expected error")
- return
- } else {
- t.Fatalf("allocated a overflowed handle got unexpected error: %v", err)
- return
- }
- }
- func testUtilGet(hm *HandleManager[string], t *testing.T, h int32, expected string) {
- v, ok := hm.Get(h)
- if !ok {
- t.Fatalf("failed to get handle %d: not found", h)
- return
- }
- if v != expected {
- t.Fatalf("get handle %d result mismatched: expected %s, got %s", h, expected, v)
- return
- }
- t.Logf("get handle %d: %v", h, v)
- }
- func testUtilGetSilent(hm *HandleManager[string], t *testing.T, h int32, expected string) {
- v, ok := hm.Get(h)
- if !ok {
- t.Fatalf("failed to get handle %d: not found", h)
- return
- }
- if v != expected {
- t.Fatalf("get handle %d result mismatched: expected %s, got %s", h, expected, v)
- return
- }
- }
- func testUtilRelease(hm *HandleManager[string], t *testing.T, h int32, expected string) {
- releasedVal, ok := hm.Release(h)
- if !ok {
- t.Fatalf("failed to release handle %d: not found", h)
- return
- }
- if releasedVal != expected {
- t.Fatalf("release handle %d result mismatched: expected %s, got %s", h, expected, releasedVal)
- return
- }
- t.Logf("release handle %d ok", h)
- }
- func testUtilReleaseSilent(hm *HandleManager[string], t *testing.T, h int32, expected string) {
- releasedVal, ok := hm.Release(h)
- if !ok {
- t.Fatalf("failed to release handle %d: not found", h)
- return
- }
- if releasedVal != expected {
- t.Fatalf("release handle %d result mismatched: expected %s, got %s", h, expected, releasedVal)
- return
- }
- }
|