blob: a84dcea4a43afda63e14e89c2cca2c77ceda537f [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plugin
import (
"errors"
"sort"
"sync"
"testing"
"time"
"github.com/ReneKroon/ttlcache/v2"
A6 "github.com/api7/ext-plugin-proto/go/A6"
pc "github.com/api7/ext-plugin-proto/go/A6/PrepareConf"
flatbuffers "github.com/google/flatbuffers/go"
"github.com/stretchr/testify/assert"
)
func TestPrepareConf(t *testing.T) {
InitConfCache(10 * time.Millisecond)
builder := flatbuffers.NewBuilder(1024)
pc.ReqStart(builder)
root := pc.ReqEnd(builder)
builder.Finish(root)
b := builder.FinishedBytes()
bd, _ := PrepareConf(b)
out := bd.FinishedBytes()
resp := pc.GetRootAsResp(out, 0)
assert.Equal(t, uint32(1), resp.ConfToken())
bd, _ = PrepareConf(b)
out = bd.FinishedBytes()
resp = pc.GetRootAsResp(out, 0)
assert.Equal(t, uint32(2), resp.ConfToken())
}
func prepareConfWithData(builder *flatbuffers.Builder, arg ...flatbuffers.UOffsetT) {
tes := []flatbuffers.UOffsetT{}
for i := 0; i < len(arg); i += 2 {
A6.TextEntryStart(builder)
name := arg[i]
value := arg[i+1]
A6.TextEntryAddName(builder, name)
A6.TextEntryAddValue(builder, value)
te := A6.TextEntryEnd(builder)
tes = append(tes, te)
}
pc.ReqStartConfVector(builder, len(tes))
for i := len(tes) - 1; i >= 0; i-- {
builder.PrependUOffsetT(tes[i])
}
v := builder.EndVector(len(tes))
pc.ReqStart(builder)
pc.ReqAddConf(builder, v)
root := pc.ReqEnd(builder)
builder.Finish(root)
b := builder.FinishedBytes()
PrepareConf(b)
}
func TestPrepareConfUnknownPlugin(t *testing.T) {
InitConfCache(1 * time.Millisecond)
builder := flatbuffers.NewBuilder(1024)
name := builder.CreateString("xxx")
value := builder.CreateString(`{"body":"yes"}`)
prepareConfWithData(builder, name, value)
res, _ := GetRuleConf(1)
assert.Equal(t, 0, len(res))
}
func TestPrepareConfBadConf(t *testing.T) {
InitConfCache(1 * time.Millisecond)
builder := flatbuffers.NewBuilder(1024)
f := func(in []byte) (conf interface{}, err error) {
return nil, errors.New("ouch")
}
RegisterPlugin("bad_conf", f, emptyFilter)
name := builder.CreateString("bad_conf")
value := builder.CreateString(`{"body":"yes"}`)
prepareConfWithData(builder, name, value)
res, _ := GetRuleConf(1)
assert.Equal(t, 0, len(res))
}
func TestPrepareConfConcurrently(t *testing.T) {
InitConfCache(10 * time.Millisecond)
builder := flatbuffers.NewBuilder(1024)
pc.ReqStart(builder)
root := pc.ReqEnd(builder)
builder.Finish(root)
b := builder.FinishedBytes()
n := 10
var wg sync.WaitGroup
res := make([][]byte, n)
for i := 0; i < n; i++ {
wg.Add(1)
go func(i int) {
bd, err := PrepareConf(b)
assert.Nil(t, err)
res[i] = bd.FinishedBytes()[:]
wg.Done()
}(i)
}
wg.Wait()
tokens := make([]int, n)
for i := 0; i < n; i++ {
resp := pc.GetRootAsResp(res[i], 0)
tokens[i] = int(resp.ConfToken())
}
sort.Ints(tokens)
for i := 0; i < n; i++ {
assert.Equal(t, i+1, tokens[i])
}
}
func TestGetRuleConf(t *testing.T) {
InitConfCache(1 * time.Millisecond)
builder := flatbuffers.NewBuilder(1024)
pc.ReqStart(builder)
root := pc.ReqEnd(builder)
builder.Finish(root)
b := builder.FinishedBytes()
bd, _ := PrepareConf(b)
out := bd.FinishedBytes()
resp := pc.GetRootAsResp(out, 0)
assert.Equal(t, uint32(1), resp.ConfToken())
res, _ := GetRuleConf(1)
assert.Equal(t, 0, len(res))
time.Sleep(2 * time.Millisecond)
_, err := GetRuleConf(1)
assert.Equal(t, ttlcache.ErrNotFound, err)
}
func TestGetRuleConfCheckConf(t *testing.T) {
RegisterPlugin("echo", emptyParseConf, emptyFilter)
InitConfCache(1 * time.Millisecond)
builder := flatbuffers.NewBuilder(1024)
name := builder.CreateString("echo")
value := builder.CreateString(`{"body":"yes"}`)
A6.TextEntryStart(builder)
A6.TextEntryAddName(builder, name)
A6.TextEntryAddValue(builder, value)
te := A6.TextEntryEnd(builder)
pc.ReqStartConfVector(builder, 1)
builder.PrependUOffsetT(te)
v := builder.EndVector(1)
pc.ReqStart(builder)
pc.ReqAddConf(builder, v)
root := pc.ReqEnd(builder)
builder.Finish(root)
b := builder.FinishedBytes()
PrepareConf(b)
res, _ := GetRuleConf(1)
assert.Equal(t, 1, len(res))
assert.Equal(t, "echo", res[0].Name)
}