2022-06-19 18:48:44 +00:00
|
|
|
//go:build !race
|
|
|
|
// +build !race
|
|
|
|
|
2021-12-24 17:22:24 +00:00
|
|
|
package depth
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-06-19 18:48:44 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
2021-12-24 17:22:24 +00:00
|
|
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
|
|
"github.com/c9s/bbgo/pkg/types"
|
|
|
|
)
|
|
|
|
|
2022-02-09 10:23:35 +00:00
|
|
|
var itov = fixedpoint.NewFromInt
|
|
|
|
|
2021-12-24 17:22:24 +00:00
|
|
|
func TestDepthBuffer_ReadyState(t *testing.T) {
|
2021-12-24 17:57:05 +00:00
|
|
|
buf := NewBuffer(func() (book types.SliceOrderBook, finalID int64, err error) {
|
2021-12-24 17:22:24 +00:00
|
|
|
return types.SliceOrderBook{
|
|
|
|
Bids: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(100), Volume: itov(1)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
Asks: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(99), Volume: itov(1)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
}, 33, nil
|
|
|
|
})
|
2022-06-10 06:24:13 +00:00
|
|
|
buf.SetBufferingPeriod(time.Millisecond * 5)
|
2021-12-24 17:22:24 +00:00
|
|
|
|
|
|
|
readyC := make(chan struct{})
|
|
|
|
buf.OnReady(func(snapshot types.SliceOrderBook, updates []Update) {
|
|
|
|
assert.Greater(t, len(updates), 33)
|
|
|
|
close(readyC)
|
|
|
|
})
|
|
|
|
|
|
|
|
var updateID int64 = 1
|
|
|
|
for ; updateID < 100; updateID++ {
|
|
|
|
buf.AddUpdate(
|
|
|
|
types.SliceOrderBook{
|
|
|
|
Bids: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(100), Volume: itov(updateID)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
Asks: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(99), Volume: itov(updateID)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
}, updateID)
|
|
|
|
}
|
|
|
|
|
|
|
|
<-readyC
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDepthBuffer_CorruptedUpdateAtTheBeginning(t *testing.T) {
|
|
|
|
// snapshot starts from 30,
|
|
|
|
// the first ready event should have a snapshot(30) and updates (31~50)
|
|
|
|
var snapshotFinalID int64 = 0
|
2021-12-24 17:57:05 +00:00
|
|
|
buf := NewBuffer(func() (types.SliceOrderBook, int64, error) {
|
2021-12-24 17:22:24 +00:00
|
|
|
snapshotFinalID += 30
|
|
|
|
return types.SliceOrderBook{
|
|
|
|
Bids: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(100), Volume: itov(1)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
Asks: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(99), Volume: itov(1)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
}, snapshotFinalID, nil
|
|
|
|
})
|
|
|
|
|
|
|
|
resetC := make(chan struct{}, 1)
|
|
|
|
|
|
|
|
buf.OnReset(func() {
|
|
|
|
resetC <- struct{}{}
|
|
|
|
})
|
|
|
|
|
|
|
|
var updateID int64 = 10
|
|
|
|
for ; updateID < 100; updateID++ {
|
|
|
|
if updateID == 50 {
|
|
|
|
updateID += 5
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.AddUpdate(types.SliceOrderBook{
|
|
|
|
Bids: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(100), Volume: itov(updateID)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
Asks: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(99), Volume: itov(updateID)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
}, updateID)
|
|
|
|
}
|
|
|
|
|
|
|
|
<-resetC
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDepthBuffer_ConcurrentRun(t *testing.T) {
|
|
|
|
var snapshotFinalID int64 = 0
|
2021-12-24 17:57:05 +00:00
|
|
|
buf := NewBuffer(func() (types.SliceOrderBook, int64, error) {
|
2021-12-24 17:22:24 +00:00
|
|
|
snapshotFinalID += 30
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
return types.SliceOrderBook{
|
|
|
|
Bids: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(100), Volume: itov(1)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
Asks: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(99), Volume: itov(1)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
}, snapshotFinalID, nil
|
|
|
|
})
|
|
|
|
|
|
|
|
readyCnt := 0
|
|
|
|
resetCnt := 0
|
|
|
|
pushCnt := 0
|
|
|
|
|
|
|
|
buf.OnPush(func(update Update) {
|
|
|
|
pushCnt++
|
|
|
|
})
|
|
|
|
buf.OnReady(func(snapshot types.SliceOrderBook, updates []Update) {
|
|
|
|
readyCnt++
|
|
|
|
})
|
|
|
|
buf.OnReset(func() {
|
|
|
|
resetCnt++
|
|
|
|
})
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
ticker := time.NewTicker(time.Millisecond)
|
|
|
|
defer ticker.Stop()
|
|
|
|
|
|
|
|
var updateID int64 = 10
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
assert.Greater(t, readyCnt, 1)
|
|
|
|
assert.Greater(t, resetCnt, 1)
|
|
|
|
assert.Greater(t, pushCnt, 1)
|
|
|
|
return
|
|
|
|
|
|
|
|
case <-ticker.C:
|
|
|
|
updateID++
|
|
|
|
if updateID%100 == 0 {
|
|
|
|
updateID++
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.AddUpdate(types.SliceOrderBook{
|
|
|
|
Bids: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(100), Volume: itov(updateID)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
Asks: types.PriceVolumeSlice{
|
2022-02-09 10:23:35 +00:00
|
|
|
{Price: itov(99), Volume: itov(updateID)},
|
2021-12-24 17:22:24 +00:00
|
|
|
},
|
|
|
|
}, updateID)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|