dubbo.apache.org/dubbo-go/v3@v3.1.1/cluster/router/condition/router_test.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package condition
    19  
    20  import (
    21  	"testing"
    22  )
    23  
    24  import (
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  import (
    29  	"dubbo.apache.org/dubbo-go/v3/common"
    30  	"dubbo.apache.org/dubbo-go/v3/common/config"
    31  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    32  	"dubbo.apache.org/dubbo-go/v3/common/extension"
    33  	"dubbo.apache.org/dubbo-go/v3/config_center"
    34  	"dubbo.apache.org/dubbo-go/v3/config_center/configurator"
    35  	"dubbo.apache.org/dubbo-go/v3/protocol"
    36  	"dubbo.apache.org/dubbo-go/v3/protocol/invocation"
    37  )
    38  
    39  const (
    40  	conditionAddr = "condition://127.0.0.1/com.foo.BarService"
    41  
    42  	localConsumerAddr  = "consumer://127.0.0.1/com.foo.BarService"
    43  	remoteConsumerAddr = "consumer://dubbo.apache.org/com.foo.BarService"
    44  
    45  	localProviderAddr  = "dubbo://127.0.0.1:20880/com.foo.BarService"
    46  	remoteProviderAddr = "dubbo://dubbo.apache.org:20880/com.foo.BarService"
    47  	emptyProviderAddr  = ""
    48  
    49  	region = "?region=hangzhou"
    50  	method = "getFoo"
    51  )
    52  
    53  func TestRouteMatchWhen(t *testing.T) {
    54  
    55  	rpcInvocation := invocation.NewRPCInvocation(method, nil, nil)
    56  	whenConsumerURL, _ := common.NewURL(remoteConsumerAddr)
    57  
    58  	testData := []struct {
    59  		name        string
    60  		consumerUrl *common.URL
    61  		rule        string
    62  
    63  		wantVal bool
    64  	}{
    65  		{
    66  			name:        " => host = 1.2.3.4",
    67  			consumerUrl: whenConsumerURL,
    68  			rule:        " => host = 1.2.3.4",
    69  
    70  			wantVal: true,
    71  		},
    72  		{
    73  			name:        "host = 1.2.3.4 => ",
    74  			consumerUrl: whenConsumerURL,
    75  			rule:        "host = 1.2.3.4 => ",
    76  
    77  			wantVal: false,
    78  		},
    79  		{
    80  			name:        "host = 2.2.2.2,dubbo.apache.org,3.3.3.3 => host = 1.2.3.4",
    81  			consumerUrl: whenConsumerURL,
    82  			rule:        "host = 2.2.2.2,dubbo.apache.org,3.3.3.3 => host = 1.2.3.4",
    83  
    84  			wantVal: true,
    85  		},
    86  		{
    87  			name:        "host = 2.2.2.2,dubbo.apache.org,3.3.3.3 & host !=dubbo.apache.org => host = 1.2.3.4",
    88  			consumerUrl: whenConsumerURL,
    89  			rule:        "host = 2.2.2.2,dubbo.apache.org,3.3.3.3 & host !=dubbo.apache.org => host = 1.2.3.4",
    90  
    91  			wantVal: false,
    92  		},
    93  		{
    94  			name:        "host !=4.4.4.4 & host = 2.2.2.2,dubbo.apache.org,3.3.3.3 => host = 1.2.3.4",
    95  			consumerUrl: whenConsumerURL,
    96  			rule:        "host !=4.4.4.4 & host = 2.2.2.2,dubbo.apache.org,3.3.3.3 => host = 1.2.3.4",
    97  
    98  			wantVal: true,
    99  		},
   100  		{
   101  			name:        "host !=4.4.4.* & host = 2.2.2.2,dubbo.apache.org,3.3.3.3 => host = 1.2.3.4",
   102  			consumerUrl: whenConsumerURL,
   103  			rule:        "host !=4.4.4.* & host = 2.2.2.2,dubbo.apache.org,3.3.3.3 => host = 1.2.3.4",
   104  
   105  			wantVal: true,
   106  		},
   107  		{
   108  			name:        "host = 2.2.2.2,dubbo.apache.*,3.3.3.3 & host != dubbo.apache.org => host = 1.2.3.4",
   109  			consumerUrl: whenConsumerURL,
   110  			rule:        "host = 2.2.2.2,dubbo.apache.*,3.3.3.3 & host != dubbo.apache.org => host = 1.2.3.4",
   111  
   112  			wantVal: false,
   113  		},
   114  		{
   115  			name:        "host = 2.2.2.2,dubbo.apache.*,3.3.3.3 & host != 1.1.1.2 => host = 1.2.3.4",
   116  			consumerUrl: whenConsumerURL,
   117  			rule:        "host = 2.2.2.2,dubbo.apache.*,3.3.3.3 & host != 1.1.1.2 => host = 1.2.3.4",
   118  
   119  			wantVal: true,
   120  		},
   121  	}
   122  
   123  	for _, data := range testData {
   124  		t.Run(data.name, func(t *testing.T) {
   125  			url, err := common.NewURL(conditionAddr)
   126  			assert.Nil(t, err)
   127  			url.AddParam(constant.RuleKey, data.rule)
   128  			router, err := NewConditionStateRouter(url)
   129  			assert.Nil(t, err)
   130  			resVal := router.matchWhen(data.consumerUrl, rpcInvocation)
   131  			assert.Equal(t, data.wantVal, resVal)
   132  		})
   133  	}
   134  }
   135  
   136  // TestRouteMatchFilter also tests pattern_value.WildcardValuePattern's Match method
   137  func TestRouteMatchFilter(t *testing.T) {
   138  
   139  	consumerURL, _ := common.NewURL(localConsumerAddr)
   140  	url1, _ := common.NewURL(remoteProviderAddr + "?serialization=fastjson")
   141  	url2, _ := common.NewURL(localProviderAddr)
   142  	url3, _ := common.NewURL(localProviderAddr)
   143  
   144  	rpcInvocation := invocation.NewRPCInvocation(method, nil, nil)
   145  
   146  	ink1 := protocol.NewBaseInvoker(url1)
   147  	ink2 := protocol.NewBaseInvoker(url2)
   148  	ink3 := protocol.NewBaseInvoker(url3)
   149  
   150  	invokerList := make([]protocol.Invoker, 0, 3)
   151  	invokerList = append(invokerList, ink1)
   152  	invokerList = append(invokerList, ink2)
   153  	invokerList = append(invokerList, ink3)
   154  
   155  	testData := []struct {
   156  		name        string
   157  		comsumerURL *common.URL
   158  		rule        string
   159  
   160  		wantVal int
   161  	}{
   162  		{
   163  			name:        "host = 127.0.0.1 => host = dubbo.apache.org",
   164  			comsumerURL: consumerURL,
   165  			rule:        "host = 127.0.0.1 => host = dubbo.apache.org",
   166  
   167  			wantVal: 1,
   168  		},
   169  		{
   170  			name:        "host = 127.0.0.1 => host = 10.20.3.* & host != dubbo.apache.org",
   171  			comsumerURL: consumerURL,
   172  			rule:        "host = 127.0.0.1 => host = 10.20.3.* & host != dubbo.apache.org",
   173  
   174  			wantVal: 0,
   175  		},
   176  		{
   177  			name:        "host = 127.0.0.1 => host = dubbo.apache.org  & host != dubbo.apache.org",
   178  			comsumerURL: consumerURL,
   179  			rule:        "host = 127.0.0.1 => host = dubbo.apache.org  & host != dubbo.apache.org",
   180  
   181  			wantVal: 0,
   182  		},
   183  		{
   184  			name:        "host = 127.0.0.1 => host = 10.20.3.2,dubbo.apache.org,10.20.3.4",
   185  			comsumerURL: consumerURL,
   186  			rule:        "host = 127.0.0.1 => host = 10.20.3.2,dubbo.apache.org,10.20.3.4",
   187  
   188  			wantVal: 1,
   189  		},
   190  		{
   191  			name:        "host = 127.0.0.1 => host != dubbo.apache.org",
   192  			comsumerURL: consumerURL,
   193  			rule:        "host = 127.0.0.1 => host != dubbo.apache.org",
   194  
   195  			wantVal: 2,
   196  		},
   197  		{
   198  			name:        "host = 127.0.0.1 => serialization = fastjson",
   199  			comsumerURL: consumerURL,
   200  			rule:        "host = 127.0.0.1 => serialization = fastjson",
   201  
   202  			wantVal: 1,
   203  		},
   204  	}
   205  
   206  	for _, data := range testData {
   207  		t.Run(data.name, func(t *testing.T) {
   208  			url, err := common.NewURL(conditionAddr)
   209  			assert.Nil(t, err)
   210  			url.AddParam(constant.RuleKey, data.rule)
   211  			url.AddParam(constant.ForceKey, "true")
   212  
   213  			router, err := NewConditionStateRouter(url)
   214  			assert.Nil(t, err)
   215  
   216  			filteredInvokers := router.Route(invokerList, data.comsumerURL, rpcInvocation)
   217  			resVal := len(filteredInvokers)
   218  			assert.Equal(t, data.wantVal, resVal)
   219  		})
   220  	}
   221  }
   222  
   223  func TestRouterMethodRoute(t *testing.T) {
   224  
   225  	rpcInvocation := invocation.NewRPCInvocation(method, nil, nil)
   226  
   227  	testData := []struct {
   228  		name        string
   229  		consumerURL string
   230  		rule        string
   231  
   232  		wantVal bool
   233  	}{
   234  		{
   235  			name:        "More than one methods, mismatch",
   236  			consumerURL: remoteConsumerAddr + "?methods=setFoo,getFoo,findFoo",
   237  			rule:        "methods=getFoo => host = 1.2.3.4",
   238  
   239  			wantVal: true,
   240  		},
   241  		{
   242  			name:        "Exactly one method, match",
   243  			consumerURL: remoteConsumerAddr + "?methods=getFoo",
   244  			rule:        "methods=getFoo => host = 1.2.3.4",
   245  
   246  			wantVal: true,
   247  		},
   248  		{
   249  			name:        "Method routing and Other condition routing can work together",
   250  			consumerURL: remoteConsumerAddr + "?methods=getFoo",
   251  			rule:        "methods=getFoo & host!=dubbo.apache.org => host = 1.2.3.4",
   252  
   253  			wantVal: false,
   254  		},
   255  	}
   256  
   257  	for _, data := range testData {
   258  		t.Run(data.name, func(t *testing.T) {
   259  			url, err := common.NewURL(conditionAddr)
   260  			assert.Nil(t, err)
   261  			url.AddParam(constant.RuleKey, data.rule)
   262  			router, err := NewConditionStateRouter(url)
   263  			assert.Nil(t, err)
   264  			consumer, _ := common.NewURL(data.consumerURL)
   265  			resVal := router.matchWhen(consumer, rpcInvocation)
   266  			assert.Equal(t, data.wantVal, resVal)
   267  		})
   268  	}
   269  }
   270  
   271  func TestRouteReturn(t *testing.T) {
   272  
   273  	rpcInvocation := invocation.NewRPCInvocation(method, nil, nil)
   274  	consumerURL, _ := common.NewURL(localConsumerAddr)
   275  
   276  	testData := []struct {
   277  		name string
   278  		urls []string
   279  		rule string
   280  
   281  		wantUrls []string
   282  		wantVal  int
   283  	}{
   284  		{
   285  			name: "ReturnFalse",
   286  			urls: []string{
   287  				emptyProviderAddr,
   288  				emptyProviderAddr,
   289  				emptyProviderAddr,
   290  			},
   291  			rule: "host = 127.0.0.1 => false",
   292  
   293  			wantUrls: []string{},
   294  			wantVal:  0,
   295  		},
   296  		{
   297  			name: "ReturnEmpty",
   298  			urls: []string{
   299  				emptyProviderAddr,
   300  				emptyProviderAddr,
   301  				emptyProviderAddr,
   302  			},
   303  			rule: "host = 127.0.0.1 => ",
   304  
   305  			wantUrls: []string{},
   306  			wantVal:  0,
   307  		},
   308  		{
   309  			name: "ReturnAll",
   310  			urls: []string{
   311  				localProviderAddr,
   312  				localProviderAddr,
   313  				localProviderAddr,
   314  			},
   315  			rule: "host = 127.0.0.1 => host = 127.0.0.1",
   316  
   317  			wantUrls: []string{
   318  				localProviderAddr,
   319  				localProviderAddr,
   320  				localProviderAddr,
   321  			},
   322  			wantVal: 3,
   323  		},
   324  		{
   325  			name: "HostFilter",
   326  			urls: []string{
   327  				remoteProviderAddr,
   328  				localProviderAddr,
   329  				localProviderAddr,
   330  			},
   331  			rule: "host = 127.0.0.1 => host = 127.0.0.1",
   332  
   333  			wantUrls: []string{
   334  				localProviderAddr,
   335  				localProviderAddr,
   336  			},
   337  			wantVal: 2,
   338  		},
   339  		{
   340  			name: "EmptyHostFilter",
   341  			urls: []string{
   342  				remoteProviderAddr,
   343  				localProviderAddr,
   344  				localProviderAddr,
   345  			},
   346  			rule: " => host = 127.0.0.1",
   347  
   348  			wantUrls: []string{
   349  				localProviderAddr,
   350  				localProviderAddr,
   351  			},
   352  			wantVal: 2,
   353  		},
   354  		{
   355  			name: "FalseHostFilter",
   356  			urls: []string{
   357  				remoteProviderAddr,
   358  				localProviderAddr,
   359  				localProviderAddr,
   360  			},
   361  			rule: "true => host = 127.0.0.1",
   362  
   363  			wantUrls: []string{
   364  				localProviderAddr,
   365  				localProviderAddr,
   366  			},
   367  			wantVal: 2,
   368  		},
   369  		{
   370  			name: "PlaceHolder",
   371  			urls: []string{
   372  				remoteProviderAddr,
   373  				localProviderAddr,
   374  				localProviderAddr,
   375  			},
   376  			rule: "host = 127.0.0.1 => host = $host",
   377  
   378  			wantUrls: []string{
   379  				localProviderAddr,
   380  				localProviderAddr,
   381  			},
   382  			wantVal: 2,
   383  		},
   384  	}
   385  
   386  	for _, data := range testData {
   387  		t.Run(data.name, func(t *testing.T) {
   388  
   389  			invokers := make([]protocol.Invoker, 0, len(data.urls))
   390  			for _, urlStr := range data.urls {
   391  				url, _ := common.NewURL(urlStr)
   392  				invoker := protocol.NewBaseInvoker(url)
   393  				invokers = append(invokers, invoker)
   394  			}
   395  
   396  			wantInvokers := make([]protocol.Invoker, 0, len(data.wantUrls))
   397  			for _, wantUrlStr := range data.wantUrls {
   398  				url, _ := common.NewURL(wantUrlStr)
   399  				invoker := protocol.NewBaseInvoker(url)
   400  				wantInvokers = append(wantInvokers, invoker)
   401  			}
   402  
   403  			url, err := common.NewURL(conditionAddr)
   404  			assert.Nil(t, err)
   405  			url.AddParam(constant.RuleKey, data.rule)
   406  			router, err := NewConditionStateRouter(url)
   407  			assert.Nil(t, err)
   408  
   409  			filterInvokers := router.Route(invokers, consumerURL, rpcInvocation)
   410  			resVal := len(filterInvokers)
   411  
   412  			assert.Equal(t, data.wantVal, resVal)
   413  			assert.Equal(t, wantInvokers, filterInvokers)
   414  		})
   415  	}
   416  }
   417  
   418  // TestRouteArguments also tests matcher.ArgumentConditionMatcher's GetValue method
   419  func TestRouteArguments(t *testing.T) {
   420  
   421  	url1, _ := common.NewURL(remoteProviderAddr)
   422  	url2, _ := common.NewURL(localProviderAddr)
   423  	url3, _ := common.NewURL(localProviderAddr)
   424  
   425  	ink1 := protocol.NewBaseInvoker(url1)
   426  	ink2 := protocol.NewBaseInvoker(url2)
   427  	ink3 := protocol.NewBaseInvoker(url3)
   428  
   429  	invokerList := make([]protocol.Invoker, 0, 3)
   430  	invokerList = append(invokerList, ink1)
   431  	invokerList = append(invokerList, ink2)
   432  	invokerList = append(invokerList, ink3)
   433  
   434  	consumerURL, _ := common.NewURL(localConsumerAddr)
   435  
   436  	testData := []struct {
   437  		name     string
   438  		argument interface{}
   439  		rule     string
   440  
   441  		wantVal int
   442  	}{
   443  		{
   444  			name:     "Empty arguments",
   445  			argument: nil,
   446  			rule:     "arguments[0] = a => host = 1.2.3.4",
   447  
   448  			wantVal: 3,
   449  		},
   450  		{
   451  			name:     "String arguments",
   452  			argument: "a",
   453  			rule:     "arguments[0] = a => host = 1.2.3.4",
   454  
   455  			wantVal: 0,
   456  		},
   457  		{
   458  			name:     "Int arguments",
   459  			argument: 1,
   460  			rule:     "arguments[0] = 1 => host = 127.0.0.1",
   461  
   462  			wantVal: 2,
   463  		},
   464  	}
   465  
   466  	for _, data := range testData {
   467  		t.Run(data.name, func(t *testing.T) {
   468  
   469  			url, err := common.NewURL(conditionAddr)
   470  			assert.Nil(t, err)
   471  			url.AddParam(constant.RuleKey, data.rule)
   472  			url.AddParam(constant.ForceKey, "true")
   473  			router, err := NewConditionStateRouter(url)
   474  			assert.Nil(t, err)
   475  
   476  			arguments := make([]interface{}, 0, 1)
   477  			arguments = append(arguments, data.argument)
   478  
   479  			rpcInvocation := invocation.NewRPCInvocation("getBar", arguments, nil)
   480  
   481  			filterInvokers := router.Route(invokerList, consumerURL, rpcInvocation)
   482  			resVal := len(filterInvokers)
   483  			assert.Equal(t, data.wantVal, resVal)
   484  
   485  		})
   486  	}
   487  }
   488  
   489  // TestRouteAttachments also tests matcher.AttachmentConditionMatcher's GetValue method
   490  func TestRouteAttachments(t *testing.T) {
   491  	consumerURL, _ := common.NewURL(localConsumerAddr)
   492  
   493  	url1, _ := common.NewURL(remoteProviderAddr + region)
   494  	url2, _ := common.NewURL(localProviderAddr)
   495  	url3, _ := common.NewURL(localProviderAddr)
   496  
   497  	ink1 := protocol.NewBaseInvoker(url1)
   498  	ink2 := protocol.NewBaseInvoker(url2)
   499  	ink3 := protocol.NewBaseInvoker(url3)
   500  
   501  	invokerList := make([]protocol.Invoker, 0, 3)
   502  	invokerList = append(invokerList, ink1)
   503  	invokerList = append(invokerList, ink2)
   504  	invokerList = append(invokerList, ink3)
   505  
   506  	testData := []struct {
   507  		name            string
   508  		attachmentKey   string
   509  		attachmentValue string
   510  		rule            string
   511  
   512  		wantVal int
   513  	}{
   514  		{
   515  			name:            "Empty attachments",
   516  			attachmentKey:   "",
   517  			attachmentValue: "",
   518  			rule:            "attachments[foo] = a => host = 1.2.3.4",
   519  
   520  			wantVal: 3,
   521  		},
   522  		{
   523  			name:            "Yes attachments and no host",
   524  			attachmentKey:   "foo",
   525  			attachmentValue: "a",
   526  			rule:            "attachments[foo] = a => host = 1.2.3.4",
   527  
   528  			wantVal: 0,
   529  		},
   530  		{
   531  			name:            "No attachments and no host",
   532  			attachmentKey:   "foo",
   533  			attachmentValue: "a",
   534  			rule:            "attachments = a => host = 1.2.3.4",
   535  
   536  			wantVal: 3,
   537  		},
   538  		{
   539  			name:            "Yes attachments and region",
   540  			attachmentKey:   "foo",
   541  			attachmentValue: "a",
   542  			rule:            "attachments[foo] = a => region = hangzhou",
   543  
   544  			wantVal: 1,
   545  		},
   546  	}
   547  
   548  	for _, data := range testData {
   549  		t.Run(data.name, func(t *testing.T) {
   550  
   551  			rpcInvocation := invocation.NewRPCInvocation(method, nil, nil)
   552  			rpcInvocation.SetAttachment(data.attachmentKey, data.attachmentValue)
   553  
   554  			url, err := common.NewURL(conditionAddr)
   555  			assert.Nil(t, err)
   556  			url.AddParam(constant.RuleKey, data.rule)
   557  			url.AddParam(constant.ForceKey, "true")
   558  			router, err := NewConditionStateRouter(url)
   559  			assert.Nil(t, err)
   560  
   561  			filterInvokers := router.Route(invokerList, consumerURL, rpcInvocation)
   562  
   563  			resVal := len(filterInvokers)
   564  			assert.Equal(t, data.wantVal, resVal)
   565  		})
   566  	}
   567  }
   568  
   569  // TestRouteRangePattern also tests pattern_value.ScopeValuePattern's Match method
   570  func TestRouteRangePattern(t *testing.T) {
   571  
   572  	consumerURL, _ := common.NewURL(localConsumerAddr)
   573  
   574  	url1, _ := common.NewURL(remoteProviderAddr + region)
   575  	url2, _ := common.NewURL(localProviderAddr)
   576  	url3, _ := common.NewURL(localProviderAddr)
   577  
   578  	ink1 := protocol.NewBaseInvoker(url1)
   579  	ink2 := protocol.NewBaseInvoker(url2)
   580  	ink3 := protocol.NewBaseInvoker(url3)
   581  
   582  	invokerList := make([]protocol.Invoker, 0, 3)
   583  	invokerList = append(invokerList, ink1)
   584  	invokerList = append(invokerList, ink2)
   585  	invokerList = append(invokerList, ink3)
   586  
   587  	testData := []struct {
   588  		name            string
   589  		attachmentKey   string
   590  		attachmentValue string
   591  		rule            string
   592  
   593  		wantVal int
   594  	}{
   595  		{
   596  			name:            "Empty attachment",
   597  			attachmentKey:   "",
   598  			attachmentValue: "",
   599  			rule:            "attachments[user_id] = 1~100 => region=hangzhou",
   600  
   601  			wantVal: 3,
   602  		},
   603  		{
   604  			name:            "In the range",
   605  			attachmentKey:   "user_id",
   606  			attachmentValue: "80",
   607  			rule:            "attachments[user_id] = 1~100 => region=hangzhou",
   608  
   609  			wantVal: 1,
   610  		},
   611  		{
   612  			name:            "Out of range",
   613  			attachmentKey:   "user_id",
   614  			attachmentValue: "101",
   615  			rule:            "attachments[user_id] = 1~100 => region=hangzhou",
   616  
   617  			wantVal: 3,
   618  		},
   619  		{
   620  			name:            "In the single interval range",
   621  			attachmentKey:   "user_id",
   622  			attachmentValue: "1",
   623  			rule:            "attachments[user_id] = ~100 => region=hangzhou",
   624  
   625  			wantVal: 1,
   626  		},
   627  		{
   628  			name:            "Not in the single interval range",
   629  			attachmentKey:   "user_id",
   630  			attachmentValue: "101",
   631  			rule:            "attachments[user_id] = ~100 => region=hangzhou",
   632  
   633  			wantVal: 3,
   634  		},
   635  	}
   636  
   637  	for _, data := range testData {
   638  		t.Run(data.name, func(t *testing.T) {
   639  
   640  			rpcInvocation := invocation.NewRPCInvocation(method, nil, nil)
   641  			rpcInvocation.SetAttachment(data.attachmentKey, data.attachmentValue)
   642  
   643  			url, err := common.NewURL(conditionAddr)
   644  			assert.Nil(t, err)
   645  			url.AddParam(constant.RuleKey, data.rule)
   646  			url.AddParam(constant.ForceKey, "true")
   647  			router, err := NewConditionStateRouter(url)
   648  			assert.Nil(t, err)
   649  
   650  			filterInvokers := router.Route(invokerList, consumerURL, rpcInvocation)
   651  
   652  			resVal := len(filterInvokers)
   653  			assert.Equal(t, data.wantVal, resVal)
   654  		})
   655  	}
   656  }
   657  
   658  func TestRouteMultipleConditions(t *testing.T) {
   659  	url1, _ := common.NewURL(remoteProviderAddr + region)
   660  	url2, _ := common.NewURL(localProviderAddr)
   661  	url3, _ := common.NewURL(localProviderAddr)
   662  
   663  	ink1 := protocol.NewBaseInvoker(url1)
   664  	ink2 := protocol.NewBaseInvoker(url2)
   665  	ink3 := protocol.NewBaseInvoker(url3)
   666  
   667  	invokerList := make([]protocol.Invoker, 0, 3)
   668  	invokerList = append(invokerList, ink1)
   669  	invokerList = append(invokerList, ink2)
   670  	invokerList = append(invokerList, ink3)
   671  
   672  	testData := []struct {
   673  		name        string
   674  		argument    string
   675  		consumerURL string
   676  		rule        string
   677  
   678  		wantVal int
   679  	}{
   680  		{
   681  			name:        "All conditions match",
   682  			argument:    "a",
   683  			consumerURL: localConsumerAddr + "?application=consumer_app",
   684  			rule:        "application=consumer_app&arguments[0]=a => host = 127.0.0.1",
   685  
   686  			wantVal: 2,
   687  		},
   688  		{
   689  			name:        "One of the conditions does not match",
   690  			argument:    "a",
   691  			consumerURL: localConsumerAddr + "?application=another_consumer_app",
   692  			rule:        "application=consumer_app&arguments[0]=a => host = 127.0.0.1",
   693  
   694  			wantVal: 3,
   695  		},
   696  	}
   697  	for _, data := range testData {
   698  		t.Run(data.name, func(t *testing.T) {
   699  			consumerUrl, err := common.NewURL(data.consumerURL)
   700  			assert.Nil(t, err)
   701  
   702  			url, err := common.NewURL(conditionAddr)
   703  			assert.Nil(t, err)
   704  			url.AddParam(constant.RuleKey, data.rule)
   705  			url.AddParam(constant.ForceKey, "true")
   706  			router, err := NewConditionStateRouter(url)
   707  			assert.Nil(t, err)
   708  
   709  			arguments := make([]interface{}, 0, 1)
   710  			arguments = append(arguments, data.argument)
   711  
   712  			rpcInvocation := invocation.NewRPCInvocation(method, arguments, nil)
   713  
   714  			filterInvokers := router.Route(invokerList, consumerUrl, rpcInvocation)
   715  			resVal := len(filterInvokers)
   716  			assert.Equal(t, data.wantVal, resVal)
   717  		})
   718  	}
   719  }
   720  
   721  func TestServiceRouter(t *testing.T) {
   722  
   723  	consumerURL, _ := common.NewURL(remoteConsumerAddr)
   724  
   725  	url1, _ := common.NewURL(remoteProviderAddr)
   726  	url2, _ := common.NewURL(remoteProviderAddr + region)
   727  	url3, _ := common.NewURL(localProviderAddr)
   728  
   729  	ink1 := protocol.NewBaseInvoker(url1)
   730  	ink2 := protocol.NewBaseInvoker(url2)
   731  	ink3 := protocol.NewBaseInvoker(url3)
   732  
   733  	invokerList := make([]protocol.Invoker, 0, 3)
   734  	invokerList = append(invokerList, ink1)
   735  	invokerList = append(invokerList, ink2)
   736  	invokerList = append(invokerList, ink3)
   737  
   738  	extension.SetDefaultConfigurator(configurator.NewMockConfigurator)
   739  	ccURL, _ := common.NewURL("mock://127.0.0.1:1111")
   740  	mockFactory := &config_center.MockDynamicConfigurationFactory{
   741  		Content: `
   742  scope: service
   743  force: true
   744  enabled: true
   745  runtime: true
   746  key: com.foo.BarService
   747  conditions:
   748   - 'method=sayHello => region=hangzhou'`,
   749  	}
   750  	dc, _ := mockFactory.GetDynamicConfiguration(ccURL)
   751  	config.GetEnvInstance().SetDynamicConfiguration(dc)
   752  
   753  	router := NewServiceRouter()
   754  	router.Notify(invokerList)
   755  
   756  	rpcInvocation := invocation.NewRPCInvocation("sayHello", nil, nil)
   757  	invokers := router.Route(invokerList, consumerURL, rpcInvocation)
   758  	assert.Equal(t, 1, len(invokers))
   759  
   760  	rpcInvocation = invocation.NewRPCInvocation("sayHi", nil, nil)
   761  	invokers = router.Route(invokerList, consumerURL, rpcInvocation)
   762  	assert.Equal(t, 3, len(invokers))
   763  }
   764  
   765  func TestApplicationRouter(t *testing.T) {
   766  
   767  	consumerURL, _ := common.NewURL(remoteConsumerAddr)
   768  
   769  	url1, _ := common.NewURL(remoteProviderAddr + "?application=demo-provider")
   770  	url2, _ := common.NewURL(localProviderAddr + "?application=demo-provider&region=hangzhou")
   771  	url3, _ := common.NewURL(localProviderAddr + "?application=demo-provider")
   772  
   773  	ink1 := protocol.NewBaseInvoker(url1)
   774  	ink2 := protocol.NewBaseInvoker(url2)
   775  	ink3 := protocol.NewBaseInvoker(url3)
   776  
   777  	invokerList := make([]protocol.Invoker, 0, 3)
   778  	invokerList = append(invokerList, ink1)
   779  	invokerList = append(invokerList, ink2)
   780  	invokerList = append(invokerList, ink3)
   781  
   782  	extension.SetDefaultConfigurator(configurator.NewMockConfigurator)
   783  	ccURL, _ := common.NewURL("mock://127.0.0.1:1111")
   784  	mockFactory := &config_center.MockDynamicConfigurationFactory{
   785  		Content: `
   786  scope: application
   787  force: true
   788  enabled: true
   789  runtime: true
   790  key: demo-provider
   791  conditions:
   792   - 'method=sayHello => region=hangzhou'`,
   793  	}
   794  	dc, _ := mockFactory.GetDynamicConfiguration(ccURL)
   795  	config.GetEnvInstance().SetDynamicConfiguration(dc)
   796  
   797  	router := NewApplicationRouter()
   798  	router.Notify(invokerList)
   799  
   800  	rpcInvocation := invocation.NewRPCInvocation("sayHello", nil, nil)
   801  	invokers := router.Route(invokerList, consumerURL, rpcInvocation)
   802  	assert.Equal(t, 1, len(invokers))
   803  
   804  	rpcInvocation = invocation.NewRPCInvocation("sayHi", nil, nil)
   805  	invokers = router.Route(invokerList, consumerURL, rpcInvocation)
   806  	assert.Equal(t, 3, len(invokers))
   807  }