mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
305 lines
6.4 KiB
Go
305 lines
6.4 KiB
Go
package gnatsd
|
|
|
|
import (
|
|
"bytes"
|
|
"runtime"
|
|
"runtime/debug"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func verifyCount(s *Sublist, count uint32, t *testing.T) {
|
|
if s.Count() != count {
|
|
t.Errorf("Count is %d, should be %d", s.Count(), count)
|
|
}
|
|
}
|
|
|
|
func verifyLen(r []interface{}, l int, t *testing.T) {
|
|
if len(r) != l {
|
|
t.Errorf("Results len is %d, should be %d", len(r), l)
|
|
}
|
|
}
|
|
|
|
func verifyMember(r []interface{}, val string, t *testing.T) {
|
|
for _, v := range r {
|
|
if v == nil {
|
|
continue
|
|
}
|
|
if v.(string) == val {
|
|
return
|
|
}
|
|
}
|
|
t.Errorf("Value '%s' not found in results", val)
|
|
}
|
|
|
|
func verifyNumLevels(s *Sublist, expected int, t *testing.T) {
|
|
dl := s.DebugNumLevels()
|
|
if dl != expected {
|
|
t.Errorf("NumLevels is %d, should be %d", dl, expected)
|
|
}
|
|
}
|
|
|
|
func TestInit(t *testing.T) {
|
|
s := New()
|
|
verifyCount(s, 0, t)
|
|
}
|
|
|
|
func TestInsertCount(t *testing.T) {
|
|
s := New()
|
|
s.Insert([]byte("foo"), "a")
|
|
s.Insert([]byte("bar"), "b")
|
|
s.Insert([]byte("foo.bar"), "b")
|
|
verifyCount(s, 3, t)
|
|
}
|
|
|
|
func TestSimple(t *testing.T) {
|
|
s := New()
|
|
val := "a"
|
|
sub := []byte("foo")
|
|
s.Insert(sub, val)
|
|
r := s.Match(sub)
|
|
verifyLen(r, 1, t)
|
|
verifyMember(r, val, t)
|
|
}
|
|
|
|
func TestSimpleMultiTokens(t *testing.T) {
|
|
s := New()
|
|
val := "a"
|
|
sub := []byte("foo.bar.baz")
|
|
s.Insert(sub, val)
|
|
r := s.Match(sub)
|
|
verifyLen(r, 1, t)
|
|
verifyMember(r, val, t)
|
|
}
|
|
|
|
func TestPartialWildcard(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.c")
|
|
pwc := []byte("a.*.c")
|
|
a, b := "a", "b"
|
|
s.Insert(literal, a)
|
|
s.Insert(pwc, b)
|
|
r := s.Match(literal)
|
|
verifyLen(r, 2, t)
|
|
verifyMember(r, a, t)
|
|
verifyMember(r, b, t)
|
|
}
|
|
|
|
func TestPartialWildcardAtEnd(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.c")
|
|
pwc := []byte("a.b.*")
|
|
a, b := "a", "b"
|
|
s.Insert(literal, a)
|
|
s.Insert(pwc, b)
|
|
r := s.Match(literal)
|
|
verifyLen(r, 2, t)
|
|
verifyMember(r, a, t)
|
|
verifyMember(r, b, t)
|
|
}
|
|
|
|
func TestFullWildcard(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.c")
|
|
fwc := []byte("a.>")
|
|
a, b := "a", "b"
|
|
s.Insert(literal, a)
|
|
s.Insert(fwc, b)
|
|
r := s.Match(literal)
|
|
verifyLen(r, 2, t)
|
|
verifyMember(r, a, t)
|
|
verifyMember(r, b, t)
|
|
}
|
|
|
|
func TestRemove(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.c.d")
|
|
value := "foo"
|
|
s.Insert(literal, value)
|
|
verifyCount(s, 1, t)
|
|
s.Remove(literal, "bar")
|
|
verifyCount(s, 1, t)
|
|
s.Remove([]byte("a.b.c"), value)
|
|
verifyCount(s, 1, t)
|
|
s.Remove(literal, value)
|
|
verifyCount(s, 0, t)
|
|
r := s.Match(literal)
|
|
verifyLen(r, 0, t)
|
|
}
|
|
|
|
func TestRemoveWildcard(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.c.d")
|
|
pwc := []byte("a.b.*.d")
|
|
fwc := []byte("a.b.>")
|
|
value := "foo"
|
|
s.Insert(pwc, value)
|
|
s.Insert(fwc, value)
|
|
s.Insert(literal, value)
|
|
verifyCount(s, 3, t)
|
|
r := s.Match(literal)
|
|
verifyLen(r, 3, t)
|
|
s.Remove(literal, value)
|
|
verifyCount(s, 2, t)
|
|
s.Remove(fwc, value)
|
|
verifyCount(s, 1, t)
|
|
s.Remove(pwc, value)
|
|
verifyCount(s, 0, t)
|
|
}
|
|
|
|
func TestRemoveCleanup(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.c.d.e.f")
|
|
depth := len(bytes.Split(literal, []byte(".")))
|
|
value := "foo"
|
|
verifyNumLevels(s, 0, t)
|
|
s.Insert(literal, value)
|
|
verifyNumLevels(s, depth, t)
|
|
s.Remove(literal, value)
|
|
verifyNumLevels(s, 0, t)
|
|
}
|
|
|
|
func TestRemoveCleanupWildcards(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.*.d.e.>")
|
|
depth := len(bytes.Split(literal, []byte(".")))
|
|
value := "foo"
|
|
verifyNumLevels(s, 0, t)
|
|
s.Insert(literal, value)
|
|
verifyNumLevels(s, depth, t)
|
|
s.Remove(literal, value)
|
|
verifyNumLevels(s, 0, t)
|
|
}
|
|
|
|
func TestCacheBehavior(t *testing.T) {
|
|
s := New()
|
|
literal := []byte("a.b.c")
|
|
fwc := []byte("a.>")
|
|
a, b := "a", "b"
|
|
s.Insert(literal, a)
|
|
r := s.Match(literal)
|
|
verifyLen(r, 1, t)
|
|
s.Insert(fwc, b)
|
|
r = s.Match(literal)
|
|
verifyLen(r, 2, t)
|
|
verifyMember(r, a, t)
|
|
verifyMember(r, b, t)
|
|
s.Remove(fwc, b)
|
|
r = s.Match(literal)
|
|
verifyLen(r, 1, t)
|
|
verifyMember(r, a, t)
|
|
}
|
|
|
|
func checkBool(b, expected bool, t *testing.T) {
|
|
if b != expected {
|
|
debug.PrintStack()
|
|
t.Fatalf("Expected %v, but got %v\n", expected, b)
|
|
}
|
|
}
|
|
|
|
func TestMatchLiterals(t *testing.T) {
|
|
checkBool(matchLiteral([]byte("foo"), []byte("foo")), true, t)
|
|
checkBool(matchLiteral([]byte("foo"), []byte("bar")), false, t)
|
|
checkBool(matchLiteral([]byte("foo"), []byte("*")), true, t)
|
|
checkBool(matchLiteral([]byte("foo"), []byte(">")), true, t)
|
|
checkBool(matchLiteral([]byte("foo.bar"), []byte(">")), true, t)
|
|
checkBool(matchLiteral([]byte("foo.bar"), []byte("foo.>")), true, t)
|
|
checkBool(matchLiteral([]byte("foo.bar"), []byte("bar.>")), false, t)
|
|
}
|
|
|
|
var subs [][]byte
|
|
var toks = []string{"apcera", "continuum", "component", "router", "api", "imgr", "jmgr", "auth"}
|
|
var sl = New()
|
|
var results = make([]interface{}, 0, 64)
|
|
|
|
func init() {
|
|
subs = make([][]byte, 0, 256*1024)
|
|
subsInit("")
|
|
for i := 0; i < len(subs); i++ {
|
|
sl.Insert(subs[i], subs[i])
|
|
}
|
|
addWildcards()
|
|
println("Sublist holding ", sl.Count(), " subscriptions")
|
|
}
|
|
|
|
func subsInit(pre string) {
|
|
var sub string
|
|
for _, t := range toks {
|
|
if len(pre) > 0 {
|
|
sub = pre + "." + t
|
|
} else {
|
|
sub = t
|
|
}
|
|
subs = append(subs, []byte(sub))
|
|
if len(strings.Split(sub, ".")) < 5 {
|
|
subsInit(sub)
|
|
}
|
|
}
|
|
}
|
|
|
|
func addWildcards() {
|
|
sl.Insert([]byte("cloud.>"), "paas")
|
|
sl.Insert([]byte("cloud.continuum.component.>"), "health")
|
|
sl.Insert([]byte("cloud.*.*.router.*"), "traffic")
|
|
}
|
|
|
|
func Benchmark______________________Insert(b *testing.B) {
|
|
b.SetBytes(1)
|
|
s := New()
|
|
for i, l := 0, len(subs); i < b.N; i++ {
|
|
index := i % l
|
|
s.Insert(subs[index], subs[index])
|
|
}
|
|
}
|
|
|
|
func Benchmark____________MatchSingleToken(b *testing.B) {
|
|
b.SetBytes(1)
|
|
s := []byte("apcera")
|
|
for i := 0; i < b.N; i++ {
|
|
sl.Match(s)
|
|
}
|
|
}
|
|
|
|
func Benchmark______________MatchTwoTokens(b *testing.B) {
|
|
b.SetBytes(1)
|
|
s := []byte("apcera.continuum")
|
|
for i := 0; i < b.N; i++ {
|
|
sl.Match(s)
|
|
}
|
|
}
|
|
|
|
func Benchmark_MatchFourTokensSingleResult(b *testing.B) {
|
|
b.SetBytes(1)
|
|
s := []byte("apcera.continuum.component.router")
|
|
for i := 0; i < b.N; i++ {
|
|
sl.Match(s)
|
|
}
|
|
}
|
|
|
|
func Benchmark_MatchFourTokensMultiResults(b *testing.B) {
|
|
b.SetBytes(1)
|
|
s := []byte("cloud.continuum.component.router")
|
|
for i := 0; i < b.N; i++ {
|
|
sl.Match(s)
|
|
}
|
|
}
|
|
|
|
func Benchmark_______MissOnLastTokenOfFive(b *testing.B) {
|
|
b.SetBytes(1)
|
|
s := []byte("apcera.continuum.component.router.ZZZZ")
|
|
for i := 0; i < b.N; i++ {
|
|
sl.Match(s)
|
|
}
|
|
}
|
|
|
|
func _BenchmarkRSS(b *testing.B) {
|
|
runtime.GC()
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
println("HEAP:", m.HeapObjects)
|
|
println("ALLOC:", m.Alloc)
|
|
println("TOTAL ALLOC:", m.TotalAlloc)
|
|
time.Sleep(30 * 1e9)
|
|
}
|