blob: 71fc097c8bf4752e0cb2b451b0da7e16480b0701 [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 filter_impl
import (
"context"
"regexp"
"testing"
)
import (
"github.com/afex/hystrix-go/hystrix"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
import (
"github.com/apache/dubbo-go/protocol"
"github.com/apache/dubbo-go/protocol/invocation"
)
func init() {
mockInitHystrixConfig()
}
func TestNewHystrixFilterError(t *testing.T) {
get := NewHystrixFilterError(errors.New("test"), true)
assert.True(t, get.(*HystrixFilterError).FailByHystrix())
assert.Equal(t, "test", get.Error())
}
func mockInitHystrixConfig() {
//Mock config
confConsumer = &HystrixFilterConfig{
make(map[string]*CommandConfigWithError),
"Default",
make(map[string]ServiceHystrixConfig),
}
confConsumer.Configs["Default"] = &CommandConfigWithError{
Timeout: 1000,
MaxConcurrentRequests: 600,
RequestVolumeThreshold: 5,
SleepWindow: 5000,
ErrorPercentThreshold: 5,
Error: nil,
}
confConsumer.Configs["userp"] = &CommandConfigWithError{
Timeout: 2000,
MaxConcurrentRequests: 64,
RequestVolumeThreshold: 15,
SleepWindow: 4000,
ErrorPercentThreshold: 45,
Error: nil,
}
confConsumer.Configs["userp_m"] = &CommandConfigWithError{
Timeout: 1200,
MaxConcurrentRequests: 64,
RequestVolumeThreshold: 5,
SleepWindow: 6000,
ErrorPercentThreshold: 60,
Error: []string{
"exception",
},
}
confConsumer.Services["com.ikurento.user.UserProvider"] = ServiceHystrixConfig{
"userp",
map[string]string{
"GetUser": "userp_m",
},
}
}
func TestGetHystrixFilter(t *testing.T) {
filterGot := GetHystrixFilterConsumer()
assert.NotNil(t, filterGot)
}
func TestGetConfig_1(t *testing.T) {
mockInitHystrixConfig()
configGot := getConfig("com.ikurento.user.UserProvider", "GetUser", true)
assert.NotNil(t, configGot)
assert.Equal(t, 1200, configGot.Timeout)
assert.Equal(t, 64, configGot.MaxConcurrentRequests)
assert.Equal(t, 6000, configGot.SleepWindow)
assert.Equal(t, 60, configGot.ErrorPercentThreshold)
assert.Equal(t, 5, configGot.RequestVolumeThreshold)
}
func TestGetConfig_2(t *testing.T) {
mockInitHystrixConfig()
configGot := getConfig("com.ikurento.user.UserProvider", "GetUser0", true)
assert.NotNil(t, configGot)
assert.Equal(t, 2000, configGot.Timeout)
assert.Equal(t, 64, configGot.MaxConcurrentRequests)
assert.Equal(t, 4000, configGot.SleepWindow)
assert.Equal(t, 45, configGot.ErrorPercentThreshold)
assert.Equal(t, 15, configGot.RequestVolumeThreshold)
}
func TestGetConfig_3(t *testing.T) {
mockInitHystrixConfig()
//This should use default
configGot := getConfig("Mock.Service", "GetMock", true)
assert.NotNil(t, configGot)
assert.Equal(t, 1000, configGot.Timeout)
assert.Equal(t, 600, configGot.MaxConcurrentRequests)
assert.Equal(t, 5000, configGot.SleepWindow)
assert.Equal(t, 5, configGot.ErrorPercentThreshold)
assert.Equal(t, 5, configGot.RequestVolumeThreshold)
}
type testMockSuccessInvoker struct {
protocol.BaseInvoker
}
func (iv *testMockSuccessInvoker) Invoke(_ context.Context, _ protocol.Invocation) protocol.Result {
return &protocol.RPCResult{
Rest: "Success",
Err: nil,
}
}
type testMockFailInvoker struct {
protocol.BaseInvoker
}
func (iv *testMockFailInvoker) Invoke(_ context.Context, _ protocol.Invocation) protocol.Result {
return &protocol.RPCResult{
Err: errors.Errorf("exception"),
}
}
func TestHystrixFilter_Invoke_Success(t *testing.T) {
hf := &HystrixFilter{}
result := hf.Invoke(context.Background(), &testMockSuccessInvoker{}, &invocation.RPCInvocation{})
assert.NotNil(t, result)
assert.NoError(t, result.Error())
assert.NotNil(t, result.Result())
}
func TestHystrixFilter_Invoke_Fail(t *testing.T) {
hf := &HystrixFilter{}
result := hf.Invoke(context.Background(), &testMockFailInvoker{}, &invocation.RPCInvocation{})
assert.NotNil(t, result)
assert.Error(t, result.Error())
}
func TestHystricFilter_Invoke_CircuitBreak(t *testing.T) {
mockInitHystrixConfig()
hystrix.Flush()
hf := &HystrixFilter{COrP: true}
resChan := make(chan protocol.Result, 50)
for i := 0; i < 50; i++ {
go func() {
result := hf.Invoke(context.Background(), &testMockFailInvoker{}, &invocation.RPCInvocation{})
resChan <- result
}()
}
//This can not always pass the test when on travis due to concurrency, you can uncomment the code below and test it locally
//var lastRest bool
//for i := 0; i < 50; i++ {
// lastRest = (<-resChan).Error().(*HystrixFilterError).FailByHystrix()
//}
//Normally the last result should be true, which means the circuit has been opened
//
//assert.True(t, lastRest)
}
func TestHystricFilter_Invoke_CircuitBreak_Omit_Exception(t *testing.T) {
mockInitHystrixConfig()
hystrix.Flush()
reg, _ := regexp.Compile(".*exception.*")
regs := []*regexp.Regexp{reg}
hf := &HystrixFilter{res: map[string][]*regexp.Regexp{"": regs}, COrP: true}
resChan := make(chan protocol.Result, 50)
for i := 0; i < 50; i++ {
go func() {
result := hf.Invoke(context.Background(), &testMockFailInvoker{}, &invocation.RPCInvocation{})
resChan <- result
}()
}
//This can not always pass the test when on travis due to concurrency, you can uncomment the code below and test it locally
//time.Sleep(time.Second * 6)
//var lastRest bool
//for i := 0; i < 50; i++ {
// lastRest = (<-resChan).Error().(*HystrixFilterError).FailByHystrix()
//}
//
//assert.False(t, lastRest)
}
func TestGetHystrixFilterConsumer(t *testing.T) {
get := GetHystrixFilterConsumer()
assert.NotNil(t, get)
assert.True(t, get.(*HystrixFilter).COrP)
}
func TestGetHystrixFilterProvider(t *testing.T) {
get := GetHystrixFilterProvider()
assert.NotNil(t, get)
assert.False(t, get.(*HystrixFilter).COrP)
}