blob: 44a05cb1867dbd35bf27d2a8731e8ae7ec976eb2 [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 util
import (
"fmt"
sd "github.com/apache/servicecomb-service-center/datasource/etcd/state/kvstore"
"reflect"
"sort"
"testing"
"github.com/apache/servicecomb-service-center/pkg/log"
"github.com/stretchr/testify/assert"
)
const VERSIONRULE_BASE = 5000
func BenchmarkVersionRule_Latest_GetServicesIds(b *testing.B) {
var kvs = make([]*sd.KeyValue, VERSIONRULE_BASE)
for i := 1; i <= VERSIONRULE_BASE; i++ {
kvs[i-1] = &sd.KeyValue{
Key: []byte(fmt.Sprintf("/service/ver/1.%d", i)),
Value: []byte(fmt.Sprintf("%d", i)),
}
}
b.N = VERSIONRULE_BASE
b.ResetTimer()
for i := 0; i < b.N; i++ {
VersionRule(Latest).Match(kvs)
}
b.ReportAllocs()
// 5000 7105020 ns/op 2180198 B/op 39068 allocs/op
}
func BenchmarkVersionRule_Range_GetServicesIds(b *testing.B) {
var kvs = make([]*sd.KeyValue, VERSIONRULE_BASE)
for i := 1; i <= VERSIONRULE_BASE; i++ {
kvs[i-1] = &sd.KeyValue{
Key: []byte(fmt.Sprintf("/service/ver/1.%d", i)),
Value: []byte(fmt.Sprintf("%d", i)),
}
}
b.N = VERSIONRULE_BASE
b.ResetTimer()
for i := 0; i < b.N; i++ {
VersionRule(Range).Match(kvs, fmt.Sprintf("1.%d", i), fmt.Sprintf("1.%d", i+VERSIONRULE_BASE/10))
}
b.ReportAllocs()
// 5000 7244029 ns/op 2287389 B/op 39584 allocs/op
}
func BenchmarkVersionRule_AtLess_GetServicesIds(b *testing.B) {
var kvs = make([]*sd.KeyValue, VERSIONRULE_BASE)
for i := 1; i <= VERSIONRULE_BASE; i++ {
kvs[i-1] = &sd.KeyValue{
Key: []byte(fmt.Sprintf("/service/ver/1.%d", i)),
Value: []byte(fmt.Sprintf("%d", i)),
}
}
b.N = VERSIONRULE_BASE
b.ResetTimer()
for i := 0; i < b.N; i++ {
VersionRule(AtLess).Match(kvs, fmt.Sprintf("1.%d", i))
}
b.ReportAllocs()
// 5000 11221098 ns/op 3174720 B/op 58064 allocs/op
}
func BenchmarkParseVersionRule(b *testing.B) {
f := ParseVersionRule("latest")
kvs := []*sd.KeyValue{
{
Key: []byte("/service/ver/1.0.300"),
Value: "1.0.300",
},
{
Key: []byte("/service/ver/1.0.303"),
Value: "1.0.303",
},
{
Key: []byte("/service/ver/1.0.304"),
Value: "1.0.304",
},
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
f(kvs)
}
})
b.ReportAllocs()
}
func TestSorter(t *testing.T) {
log.Info("normal")
t.Run("version asc", func(t *testing.T) {
kvs := []string{"1.0.0", "1.0.1"}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "1.0.1", kvs[0])
assert.Equal(t, "1.0.0", kvs[1])
})
t.Run("version desc", func(t *testing.T) {
kvs := []string{"1.0.1", "1.0.0"}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "1.0.1", kvs[0])
assert.Equal(t, "1.0.0", kvs[1])
})
t.Run("len(v1) != len(v2)", func(t *testing.T) {
kvs := []string{"1.0.0.0", "1.0.1"}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "1.0.1", kvs[0])
assert.Equal(t, "1.0.0.0", kvs[1])
})
t.Run("1.0.9 vs 1.0.10", func(t *testing.T) {
kvs := []string{"1.0.9", "1.0.10"}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "1.0.10", kvs[0])
assert.Equal(t, "1.0.9", kvs[1])
})
t.Run("1.10 vs 4", func(t *testing.T) {
kvs := []string{"1.10", "4"}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "4", kvs[0])
assert.Equal(t, "1.10", kvs[1])
})
log.Info("exception")
t.Run("invalid version1", func(t *testing.T) {
kvs := []string{"1.a", "1.0.1.a", ""}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "1.a", kvs[0])
assert.Equal(t, "1.0.1.a", kvs[1])
assert.Equal(t, "", kvs[2])
})
t.Run("invalid version2 > 32767", func(t *testing.T) {
kvs := []string{"1.0", "1.0.1.32768"}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "1.0", kvs[0])
assert.Equal(t, "1.0.1.32768", kvs[1])
kvs = []string{"1.0", "1.0.1.32767"}
sort.Sort(&serviceKeySorter{
sortArr: kvs,
kvs: make(map[string]*sd.KeyValue),
cmp: Larger,
})
assert.Equal(t, "1.0.1.32767", kvs[0])
assert.Equal(t, "1.0", kvs[1])
})
}
func TestVersionRule(t *testing.T) {
const count = 10
var kvs = [count]*sd.KeyValue{}
for i := 1; i <= count; i++ {
kvs[i-1] = &sd.KeyValue{
Key: []byte(fmt.Sprintf("/service/ver/1.%d", i)),
Value: fmt.Sprintf("%d", i),
}
}
log.Info("normal")
t.Run("latest", func(t *testing.T) {
results := VersionRule(Latest).Match(kvs[:])
assert.Equal(t, 1, len(results))
assert.Equal(t, fmt.Sprintf("%d", count), results[0])
})
t.Run("range1.1 ver in [1.4, 1.8)", func(t *testing.T) {
results := VersionRule(Range).Match(kvs[:], "1.4", "1.8")
assert.Equal(t, 4, len(results))
assert.Equal(t, "7", results[0])
assert.Equal(t, "4", results[3])
})
t.Run("range1.2 ver in (1.8, 1.4]", func(t *testing.T) {
results := VersionRule(Range).Match(kvs[:], "1.8", "1.4")
assert.Equal(t, 4, len(results))
assert.Equal(t, "7", results[0])
assert.Equal(t, "4", results[3])
})
t.Run("range2 ver in [1, 2]", func(t *testing.T) {
results := VersionRule(Range).Match(kvs[:], "1", "2")
assert.Equal(t, 10, len(results))
assert.Equal(t, "10", results[0])
assert.Equal(t, "1", results[9])
})
t.Run("range3 ver in [1.4.1, 1.9.1]", func(t *testing.T) {
results := VersionRule(Range).Match(kvs[:], "1.4.1", "1.9.1")
assert.Equal(t, 5, len(results))
assert.Equal(t, "9", results[0])
assert.Equal(t, "5", results[4])
})
t.Run("range4 ver in [2, 4]", func(t *testing.T) {
results := VersionRule(Range).Match(kvs[:], "2", "4")
assert.Equal(t, len(results), 0)
})
t.Run("atLess1 ver >= 1.6", func(t *testing.T) {
results := VersionRule(AtLess).Match(kvs[:], "1.6")
assert.Equal(t, len(results), 5)
assert.Equal(t, "10", results[0])
assert.Equal(t, "6", results[4])
})
t.Run("atLess2 ver >= 1", func(t *testing.T) {
results := VersionRule(AtLess).Match(kvs[:], "1")
assert.Equal(t, len(results), 10)
assert.Equal(t, "10", results[0])
assert.Equal(t, "1", results[9])
})
t.Run("atLess3 ver >= 1.5.1", func(t *testing.T) {
results := VersionRule(AtLess).Match(kvs[:], "1.5.1")
assert.Equal(t, 5, len(results))
assert.Equal(t, "10", results[0])
assert.Equal(t, "6", results[4])
})
t.Run("atLess4 ver >= 2", func(t *testing.T) {
results := VersionRule(AtLess).Match(kvs[:], "2")
assert.Equal(t, 0, len(results))
})
log.Info("exception")
t.Run("nil", func(t *testing.T) {
results := VersionRule(Latest).Match(nil)
assert.Equal(t, 0, len(results))
results = VersionRule(AtLess).Match(nil)
assert.Equal(t, 0, len(results))
results = VersionRule(Range).Match(nil)
assert.Equal(t, 0, len(results))
rule := ParseVersionRule("")
assert.Equal(t, true, reflect.ValueOf(rule).IsNil())
rule = ParseVersionRule("abc")
assert.Equal(t, true, reflect.ValueOf(rule).IsNil())
assert.Equal(t, true, VersionMatchRule("1.0", "1.0"))
assert.Equal(t, false, VersionMatchRule("1.0", "1.2"))
})
log.Info("parse")
t.Run("latest", func(t *testing.T) {
match := ParseVersionRule("latest")
results := match(kvs[:])
assert.Equal(t, 1, len(results))
assert.Equal(t, fmt.Sprintf("%d", count), results[0])
})
t.Run("range ver in[1.4, 1.8]", func(t *testing.T) {
match := ParseVersionRule("1.4-1.8")
results := match(kvs[:])
assert.Equal(t, 4, len(results))
assert.Equal(t, "7", results[0])
assert.Equal(t, "4", results[3])
})
t.Run("atLess ver >= 1.6", func(t *testing.T) {
match := ParseVersionRule("1.6+")
results := match(kvs[:])
assert.Equal(t, 5, len(results))
assert.Equal(t, "10", results[0])
assert.Equal(t, "6", results[4])
})
log.Info("version match rule")
t.Run("latest", func(t *testing.T) {
assert.Equal(t, true, VersionMatchRule("1.0", "latest"))
})
t.Run("range ver in [1.4, 1.8]", func(t *testing.T) {
assert.Equal(t, true, VersionMatchRule("1.4", "1.4-1.8"))
assert.Equal(t, true, VersionMatchRule("1.6", "1.4-1.8"))
assert.Equal(t, false, VersionMatchRule("1.8", "1.4-1.8"))
assert.Equal(t, false, VersionMatchRule("1.0", "1.4-1.8"))
assert.Equal(t, false, VersionMatchRule("1.9", "1.4-1.8"))
})
t.Run("atLess ver >= 1.6", func(t *testing.T) {
assert.Equal(t, true, VersionMatchRule("1.6", "1.6+"))
assert.Equal(t, true, VersionMatchRule("1.9", "1.6+"))
assert.Equal(t, false, VersionMatchRule("1.0", "1.6+"))
})
}