service/tests/service_pool_test.go

225 lines
5.5 KiB
Go
Raw Permalink Normal View History

package service_test
import (
"fmt"
"sync"
"time"
"apigo.cc/gojs"
_ "apigo.cc/gojs/console"
_ "apigo.cc/gojs/http"
"apigo.cc/gojs/service"
_ "apigo.cc/gojs/service"
_ "apigo.cc/gojs/util"
2024-10-18 17:54:37 +08:00
"github.com/ssgo/discover"
"github.com/ssgo/httpclient"
"github.com/ssgo/u"
//"go.uber.org/goleak"
//_ "net/http/pprof"
"runtime"
"testing"
)
var rt2 *gojs.Runtime
var addrByPool = ""
const runTimes2 = 100
//func TestMain(m *testing.M) {
// // Verify no goroutines are leaked after tests
// goleak.VerifyTestMain(m)
//}
func TestStartByPool(t *testing.T) {
//go func() {
// fmt.Println(u.BYellow(http.ListenAndServe("localhost:6060", nil)))
//}()
gojs.ExportForDev()
rt2 = gojs.New()
err := rt2.StartFromFile("start.js")
if err != nil {
t.Fatal("start failed", err)
}
r, err := rt2.RunMain()
if err != nil {
t.Fatal("start failed", err)
}
addrByPool = u.String(r)
2024-10-18 17:54:37 +08:00
discover.SetNode("user", addrByPool, 100)
}
// TODO Caller
// TODO WS
// func TestWS(t *testing.T) {
// r, err := rt2.RunCode("testWS()")
// if err != nil {
// t.Fatal("test ws failed, got error", err)
// } else if r != true {
// t.Fatal("test ws failed", r, err)
// } else {
// fmt.Println(u.BGreen("test ws success"))
// }
// }
func TestSession(t *testing.T) {
r, err := rt2.RunCode("testUser()")
if err != nil {
t.Fatal("test user failed, got error", err, r)
} else if r != true {
t.Fatal("test user failed", r)
}
}
func TestJsEchoByPool(t *testing.T) {
for i := 0; i < runTimes2; i++ {
name := u.UniqueId()
r, err := rt2.RunCode("test2('" + name + "')")
if err != nil {
t.Fatal("test js get failed, got error", err)
} else if r != name {
t.Fatal("test js get failed, name not match", r, name)
}
}
}
func TestGoEchoByPool(t *testing.T) {
hc := httpclient.GetClientH2C(0)
for i := 0; i < runTimes2; i++ {
name := u.UniqueId()
r := hc.Get("http://" + addrByPool + "/echo2?name=" + name)
if r.Error != nil {
t.Fatal("test go get failed, got error", r.Error)
} else if r.String() != name {
t.Fatal("test go get failed, name not match", r, name)
}
}
}
func TestJsAsyncEchoByPool(t *testing.T) {
ch := make(chan bool, runTimes2)
t1 := time.Now().UnixMilli()
for i := 0; i < runTimes2; i++ {
go func() {
name := u.UniqueId()
r, err := rt2.RunCode("test2('" + name + "')")
ch <- true
if err != nil {
t.Fatal("test js async get failed, got error", err)
} else if r != name {
t.Fatal("test js async get failed, name not match", r, name)
}
}()
}
for i := 0; i < runTimes2; i++ {
<-ch
}
t2 := time.Now().UnixMilli() - t1
fmt.Println(u.BGreen("js async test time:"), t2, "ms")
}
func TestGoAsyncEchoByPool(t *testing.T) {
//defer goleak.VerifyNone(t)
hc := httpclient.GetClientH2C(0)
const taskNum = 100
const taskRunTimes = 100
for j := 0; j < 10; j++ {
ch := make(chan bool, taskNum*taskRunTimes)
t1 := time.Now().UnixMilli()
//for j := 0; j < 10; j++ {
ms1 := runtime.MemStats{}
runtime.ReadMemStats(&ms1)
okNum := 0
failedNum := 0
startNum := 0
endNum := 0
lastName := fmt.Sprint("Task_", taskNum-1, "_", taskRunTimes-1)
lastResult := ""
lastOK := false
okMap := map[string]int{}
okMapLock := sync.Mutex{}
for i1 := 0; i1 < taskNum; i1++ {
name1 := fmt.Sprint("Task_", i1, "_")
go func() {
for i2 := 0; i2 < taskRunTimes; i2++ {
name := fmt.Sprint(name1, i2)
okMapLock.Lock()
okMap[name] = 1
startNum++
okMapLock.Unlock()
r := hc.Get("http://" + addrByPool + "/echo2?name=" + name)
okMapLock.Lock()
if name == lastName {
lastResult = r.String()
lastOK = lastName == lastResult
}
if r.Error != nil {
failedNum++
t.Fatal("test go async get failed, got error", r.Error)
} else if r.String() != name {
failedNum++
t.Fatal("test go async get failed, name not match", r, name)
} else {
okMap[name] = 2
okNum++
}
endNum++
okMapLock.Unlock()
ch <- true
}
}()
}
for i := 0; i < taskNum*taskRunTimes; i++ {
<-ch
}
for i1 := 0; i1 < taskNum; i1++ {
for i2 := 0; i2 < taskRunTimes; i2++ {
name := fmt.Sprint("Task_", i1, "_", i2)
if okMap[name] != 2 {
fmt.Println(i1, i2, okMap[name])
}
}
}
if okNum != taskNum*taskRunTimes {
t.Fatal("test go async get failed, ok num is error", okNum, taskNum*taskRunTimes, failedNum, "|", startNum, ">", endNum, "||", lastName, lastResult, lastOK)
}
t2 := time.Now().UnixMilli() - t1
fmt.Println(u.Green("go async test time:"), u.BGreen(t2), "ms")
for k, status := range service.GetPoolStatus() {
fmt.Println(u.Magenta(k), u.Magenta("total"), u.BMagenta(status.Total), u.Magenta("maxTotal"), u.BMagenta(status.MaxTotal), u.Magenta("createTimes"), u.BMagenta(status.CreateTimes), u.Magenta("maxWaiting"), u.BMagenta(status.MaxWaiting))
}
//fmt.Println(u.BGreen("last name:"), lastName, lastResult, lastOK)
if !lastOK {
t.Fatal("test go async get failed, last name not match", lastName, lastResult, lastOK)
}
ms2 := runtime.MemStats{}
runtime.ReadMemStats(&ms2)
runtime.GC()
ms3 := runtime.MemStats{}
runtime.ReadMemStats(&ms3)
fmt.Println(u.Cyan("MEMORY >>"), u.BCyan(fmt.Sprintln(ms1.HeapInuse/1000000, ms2.HeapInuse/1000000, ms3.HeapInuse/1000000)))
}
//hc.Destroy()
//time.Sleep(1000 * time.Second)
}
func TestStopByPool(t *testing.T) {
_, err := rt2.RunCode("s.stop()")
if err != nil {
t.Fatal("stop failed", err)
}
gojs.WaitAll()
runtime.GC()
ms3 := runtime.MemStats{}
runtime.ReadMemStats(&ms3)
fmt.Println(u.Cyan("END MEMORY >>"), u.BCyan(ms3.HeapInuse/1000000))
}