mirror of
https://github.com/datarhei/core.git
synced 2025-10-06 00:17:07 +08:00
561 lines
11 KiB
Go
561 lines
11 KiB
Go
package session
|
|
|
|
import (
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/datarhei/core/v16/io/fs"
|
|
"github.com/lestrrat-go/strftime"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestRegister(t *testing.T) {
|
|
r, err := New(Config{})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
_, err = r.Register("", CollectorConfig{})
|
|
require.Error(t, err)
|
|
|
|
_, err = r.Register("../foo/bar", CollectorConfig{})
|
|
require.Error(t, err)
|
|
|
|
_, err = r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
_, err = r.Register("foobar", CollectorConfig{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestUnregister(t *testing.T) {
|
|
r, err := New(Config{})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
_, err = r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestCollectors(t *testing.T) {
|
|
r, err := New(Config{})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c := r.Collectors()
|
|
require.Equal(t, []string{}, c)
|
|
|
|
_, err = r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
c = r.Collectors()
|
|
require.Equal(t, []string{"foobar"}, c)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
c = r.Collectors()
|
|
require.Equal(t, []string{}, c)
|
|
}
|
|
|
|
func TestGetCollector(t *testing.T) {
|
|
r, err := New(Config{})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c := r.Collector("foobar")
|
|
require.Nil(t, c)
|
|
|
|
_, err = r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
c = r.Collector("foobar")
|
|
require.NotNil(t, c)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
c = r.Collector("foobar")
|
|
require.Nil(t, c)
|
|
}
|
|
|
|
func TestUnregisterAll(t *testing.T) {
|
|
r, err := New(Config{})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
_, err = r.Register("foo", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
_, err = r.Register("bar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
c := r.Collectors()
|
|
require.ElementsMatch(t, []string{"foo", "bar"}, c)
|
|
|
|
r.UnregisterAll()
|
|
|
|
c = r.Collectors()
|
|
require.Equal(t, []string{}, c)
|
|
}
|
|
|
|
func TestRestoreHistory(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = memfs.WriteFile("/foobar.json", []byte("{}"))
|
|
require.NoError(t, err)
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestRestoreInvalidHistory(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = memfs.WriteFile("/foobar.json", []byte(""))
|
|
require.NoError(t, err)
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
files := memfs.List("/", fs.ListOptions{})
|
|
require.Equal(t, 2, len(files))
|
|
}
|
|
|
|
func TestPersistHistory(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
_, err = memfs.Stat("/foobar.json")
|
|
require.NoError(t, err)
|
|
|
|
c, err = r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
cc := c.(*collector)
|
|
totals, ok := cc.history.Sessions["location:peer:ref"]
|
|
require.True(t, ok)
|
|
require.Equal(t, "location", totals.Location)
|
|
require.Equal(t, "ref", totals.Reference)
|
|
require.Equal(t, "peer", totals.Peer)
|
|
require.Equal(t, uint64(42), totals.TotalTxBytes)
|
|
}
|
|
|
|
type slowMemFilesystem struct {
|
|
fs.Filesystem
|
|
}
|
|
|
|
func newSlowMemFilesystem(config fs.MemConfig) (fs.Filesystem, error) {
|
|
memfs, err := fs.NewMemFilesystem(config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
f := &slowMemFilesystem{
|
|
Filesystem: memfs,
|
|
}
|
|
|
|
return f, nil
|
|
}
|
|
|
|
func (c *slowMemFilesystem) WriteFileSafe(path string, data []byte) (int64, bool, error) {
|
|
if path != "/foobar.json" {
|
|
return 0, true, nil
|
|
}
|
|
time.Sleep(2 * time.Second)
|
|
|
|
return c.Filesystem.WriteFileSafe(path, data)
|
|
}
|
|
|
|
func TestPersistHistorySlowSnapshot(t *testing.T) {
|
|
memfs, err := newSlowMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
c.Close("foo")
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
_, err = memfs.Stat("/foobar.json")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestPeriodicPersistHistory(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
PersistInterval: 5 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{
|
|
SessionTimeout: time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
require.Eventually(t, func() bool {
|
|
_, err = memfs.Stat("/foobar.json")
|
|
return err == nil
|
|
}, 10*time.Second, time.Second)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
_, err = memfs.Stat("/foobar.json")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestPersistSession(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
pattern := "/log/%Y-%m-%d.log"
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
LogPattern: pattern,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{
|
|
SessionTimeout: 3 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
r.Close()
|
|
|
|
path, err := strftime.Format(pattern, time.Now())
|
|
require.NoError(t, err)
|
|
|
|
info, err := memfs.Stat(path)
|
|
require.NoError(t, err)
|
|
require.Greater(t, info.Size(), int64(0))
|
|
}
|
|
|
|
func TestPersistSessionDelayed(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
pattern := "/log/%Y-%m-%d-%H.log"
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
LogPattern: pattern,
|
|
LogBufferDuration: 5 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{
|
|
SessionTimeout: 3 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
ce, ok := c.(*collector)
|
|
require.True(t, ok)
|
|
|
|
start, err := time.Parse(time.RFC3339, "2023-11-01T15:04:00Z")
|
|
require.NoError(t, err)
|
|
|
|
ce.sessionsCh <- Session{
|
|
Collector: "foobar",
|
|
CreatedAt: start,
|
|
ClosedAt: start.Add(5 * time.Minute),
|
|
}
|
|
|
|
ce.sessionsCh <- Session{
|
|
Collector: "foobar",
|
|
CreatedAt: start,
|
|
ClosedAt: start.Add(6 * time.Minute),
|
|
}
|
|
|
|
ce.sessionsCh <- Session{
|
|
Collector: "foobar",
|
|
CreatedAt: start,
|
|
ClosedAt: start.Add(7 * time.Minute),
|
|
}
|
|
|
|
ce.sessionsCh <- Session{
|
|
Collector: "foobar",
|
|
CreatedAt: start,
|
|
ClosedAt: start.Add(1 * time.Hour),
|
|
}
|
|
|
|
// late entry
|
|
ce.sessionsCh <- Session{
|
|
Collector: "foobar",
|
|
CreatedAt: start,
|
|
ClosedAt: start.Add(8 * time.Minute),
|
|
}
|
|
|
|
ce.sessionsCh <- Session{
|
|
Collector: "foobar",
|
|
CreatedAt: start,
|
|
ClosedAt: start.Add(61 * time.Minute),
|
|
}
|
|
|
|
require.Eventually(t, func() bool {
|
|
path, err := strftime.Format(pattern, start)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
_, err = memfs.Stat(path)
|
|
return err == nil
|
|
}, 10*time.Second, time.Second)
|
|
|
|
path, err := strftime.Format(pattern, start)
|
|
require.NoError(t, err)
|
|
|
|
file := memfs.Open(path)
|
|
require.NotNil(t, file)
|
|
|
|
data, err := io.ReadAll(file)
|
|
require.NoError(t, err)
|
|
|
|
file.Close()
|
|
|
|
lines := strings.Split(string(data), "\n")
|
|
require.Equal(t, 3, len(lines)-1)
|
|
|
|
require.Eventually(t, func() bool {
|
|
path, err := strftime.Format(pattern, start.Add(1*time.Hour))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
_, err = memfs.Stat(path)
|
|
return err == nil
|
|
}, 10*time.Second, time.Second)
|
|
|
|
path, err = strftime.Format(pattern, start.Add(1*time.Hour))
|
|
require.NoError(t, err)
|
|
|
|
file = memfs.Open(path)
|
|
require.NotNil(t, file)
|
|
|
|
data, err = io.ReadAll(file)
|
|
require.NoError(t, err)
|
|
|
|
file.Close()
|
|
|
|
lines = strings.Split(string(data), "\n")
|
|
require.Equal(t, 3, len(lines)-1)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestPersistSessionSlpit(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
pattern := "/log/%Y-%m-%d-%H:%M:%S.log"
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
LogPattern: pattern,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{
|
|
SessionTimeout: 3 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
time.Sleep(3 * time.Second)
|
|
|
|
c.RegisterAndActivate("bar", "ref", "location", "peer")
|
|
c.Egress("bar", 24)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
r.Close()
|
|
|
|
require.Equal(t, int64(2), memfs.Files())
|
|
}
|
|
|
|
func TestPersistSessionBuffer(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
pattern := "/log/%Y-%m-%d.log"
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
LogPattern: pattern,
|
|
LogBufferDuration: 5 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{
|
|
SessionTimeout: 3 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
c.RegisterAndActivate("foo", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
require.Eventually(t, func() bool {
|
|
path, err := strftime.Format(pattern, time.Now())
|
|
if err != nil {
|
|
return false
|
|
}
|
|
_, err = memfs.Stat(path)
|
|
return err == nil
|
|
}, 10*time.Second, time.Second)
|
|
|
|
err = r.Unregister("foobar")
|
|
require.NoError(t, err)
|
|
|
|
r.Close()
|
|
|
|
path, err := strftime.Format(pattern, time.Now())
|
|
require.NoError(t, err)
|
|
|
|
info, err := memfs.Stat(path)
|
|
require.NoError(t, err)
|
|
require.Greater(t, info.Size(), int64(0))
|
|
}
|
|
|
|
func TestRegisterAfterCloseWithPersist(t *testing.T) {
|
|
memfs, err := fs.NewMemFilesystem(fs.MemConfig{})
|
|
require.NoError(t, err)
|
|
|
|
pattern := "/log/%Y-%m-%d.log"
|
|
|
|
r, err := New(Config{
|
|
PersistFS: memfs,
|
|
LogPattern: pattern,
|
|
LogBufferDuration: 5 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
r.Close()
|
|
})
|
|
|
|
c, err := r.Register("foobar", CollectorConfig{
|
|
SessionTimeout: 3 * time.Second,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
for i := 0; i < 1000; i++ {
|
|
c.RegisterAndActivate("foo_"+strconv.Itoa(i), "ref", "location", "peer")
|
|
c.Egress("foo", int64(i))
|
|
}
|
|
|
|
r.Close()
|
|
|
|
c.RegisterAndActivate("foo_XXX", "ref", "location", "peer")
|
|
c.Egress("foo", 42)
|
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
require.Equal(t, int64(2), memfs.Files())
|
|
}
|