...

Source file src/google.golang.org/grpc/xds/internal/balancer/clusterresolver/config_test.go

Documentation: google.golang.org/grpc/xds/internal/balancer/clusterresolver

     1  /*
     2   *
     3   * Copyright 2021 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * 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  
    19  package clusterresolver
    20  
    21  import (
    22  	"encoding/json"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/google/go-cmp/cmp"
    27  	"github.com/google/go-cmp/cmp/cmpopts"
    28  	"google.golang.org/grpc/balancer"
    29  	"google.golang.org/grpc/balancer/roundrobin"
    30  	iserviceconfig "google.golang.org/grpc/internal/serviceconfig"
    31  	"google.golang.org/grpc/internal/xds/bootstrap"
    32  	"google.golang.org/grpc/xds/internal/balancer/outlierdetection"
    33  	"google.golang.org/grpc/xds/internal/balancer/ringhash"
    34  )
    35  
    36  func TestDiscoveryMechanismTypeMarshalJSON(t *testing.T) {
    37  	tests := []struct {
    38  		name string
    39  		typ  DiscoveryMechanismType
    40  		want string
    41  	}{
    42  		{
    43  			name: "eds",
    44  			typ:  DiscoveryMechanismTypeEDS,
    45  			want: `"EDS"`,
    46  		},
    47  		{
    48  			name: "dns",
    49  			typ:  DiscoveryMechanismTypeLogicalDNS,
    50  			want: `"LOGICAL_DNS"`,
    51  		},
    52  	}
    53  	for _, tt := range tests {
    54  		t.Run(tt.name, func(t *testing.T) {
    55  			if got, err := json.Marshal(tt.typ); err != nil || string(got) != tt.want {
    56  				t.Fatalf("DiscoveryMechanismTypeEDS.MarshalJSON() = (%v, %v), want (%s, nil)", string(got), err, tt.want)
    57  			}
    58  		})
    59  	}
    60  }
    61  func TestDiscoveryMechanismTypeUnmarshalJSON(t *testing.T) {
    62  	tests := []struct {
    63  		name    string
    64  		js      string
    65  		want    DiscoveryMechanismType
    66  		wantErr bool
    67  	}{
    68  		{
    69  			name: "eds",
    70  			js:   `"EDS"`,
    71  			want: DiscoveryMechanismTypeEDS,
    72  		},
    73  		{
    74  			name: "dns",
    75  			js:   `"LOGICAL_DNS"`,
    76  			want: DiscoveryMechanismTypeLogicalDNS,
    77  		},
    78  		{
    79  			name:    "error",
    80  			js:      `"1234"`,
    81  			wantErr: true,
    82  		},
    83  	}
    84  	for _, tt := range tests {
    85  		t.Run(tt.name, func(t *testing.T) {
    86  			var got DiscoveryMechanismType
    87  			err := json.Unmarshal([]byte(tt.js), &got)
    88  			if (err != nil) != tt.wantErr {
    89  				t.Fatalf("DiscoveryMechanismTypeEDS.UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
    90  			}
    91  			if diff := cmp.Diff(got, tt.want); diff != "" {
    92  				t.Fatalf("DiscoveryMechanismTypeEDS.UnmarshalJSON() got unexpected output, diff (-got +want): %v", diff)
    93  			}
    94  		})
    95  	}
    96  }
    97  
    98  const (
    99  	testJSONConfig1 = `{
   100    "discoveryMechanisms": [{
   101      "cluster": "test-cluster-name",
   102      "lrsLoadReportingServer": {
   103        "server_uri": "trafficdirector.googleapis.com:443",
   104        "channel_creds": [ { "type": "google_default" } ]
   105      },
   106      "maxConcurrentRequests": 314,
   107      "type": "EDS",
   108      "edsServiceName": "test-eds-service-name",
   109      "outlierDetection": {}
   110    }],
   111    "xdsLbPolicy":[{"round_robin":{}}]
   112  }`
   113  	testJSONConfig2 = `{
   114    "discoveryMechanisms": [{
   115      "cluster": "test-cluster-name",
   116      "lrsLoadReportingServer": {
   117        "server_uri": "trafficdirector.googleapis.com:443",
   118        "channel_creds": [ { "type": "google_default" } ]
   119      },
   120      "maxConcurrentRequests": 314,
   121      "type": "EDS",
   122      "edsServiceName": "test-eds-service-name",
   123      "outlierDetection": {}
   124    },{
   125      "type": "LOGICAL_DNS",
   126      "outlierDetection": {}
   127    }],
   128    "xdsLbPolicy":[{"round_robin":{}}]
   129  }`
   130  	testJSONConfig3 = `{
   131    "discoveryMechanisms": [{
   132      "cluster": "test-cluster-name",
   133      "lrsLoadReportingServer": {
   134        "server_uri": "trafficdirector.googleapis.com:443",
   135        "channel_creds": [ { "type": "google_default" } ]
   136      },
   137      "maxConcurrentRequests": 314,
   138      "type": "EDS",
   139      "edsServiceName": "test-eds-service-name",
   140      "outlierDetection": {}
   141    }],
   142    "xdsLbPolicy":[{"round_robin":{}}]
   143  }`
   144  	testJSONConfig4 = `{
   145    "discoveryMechanisms": [{
   146      "cluster": "test-cluster-name",
   147      "lrsLoadReportingServer": {
   148        "server_uri": "trafficdirector.googleapis.com:443",
   149        "channel_creds": [ { "type": "google_default" } ]
   150      },
   151      "maxConcurrentRequests": 314,
   152      "type": "EDS",
   153      "edsServiceName": "test-eds-service-name",
   154      "outlierDetection": {}
   155    }],
   156    "xdsLbPolicy":[{"ring_hash_experimental":{}}]
   157  }`
   158  	testJSONConfig5 = `{
   159    "discoveryMechanisms": [{
   160      "cluster": "test-cluster-name",
   161      "lrsLoadReportingServer": {
   162        "server_uri": "trafficdirector.googleapis.com:443",
   163        "channel_creds": [ { "type": "google_default" } ]
   164      },
   165      "maxConcurrentRequests": 314,
   166      "type": "EDS",
   167      "edsServiceName": "test-eds-service-name",
   168      "outlierDetection": {}
   169    }],
   170    "xdsLbPolicy":[{"round_robin":{}}]
   171  }`
   172  )
   173  
   174  var testLRSServerConfig = &bootstrap.ServerConfig{
   175  	ServerURI: "trafficdirector.googleapis.com:443",
   176  	Creds: bootstrap.ChannelCreds{
   177  		Type: "google_default",
   178  	},
   179  }
   180  
   181  func TestParseConfig(t *testing.T) {
   182  	tests := []struct {
   183  		name    string
   184  		js      string
   185  		want    *LBConfig
   186  		wantErr bool
   187  	}{
   188  		{
   189  			name:    "empty json",
   190  			js:      "",
   191  			want:    nil,
   192  			wantErr: true,
   193  		},
   194  		{
   195  			name: "OK with one discovery mechanism",
   196  			js:   testJSONConfig1,
   197  			want: &LBConfig{
   198  				DiscoveryMechanisms: []DiscoveryMechanism{
   199  					{
   200  						Cluster:               testClusterName,
   201  						LoadReportingServer:   testLRSServerConfig,
   202  						MaxConcurrentRequests: newUint32(testMaxRequests),
   203  						Type:                  DiscoveryMechanismTypeEDS,
   204  						EDSServiceName:        testEDSService,
   205  						outlierDetection: outlierdetection.LBConfig{
   206  							Interval:           iserviceconfig.Duration(10 * time.Second), // default interval
   207  							BaseEjectionTime:   iserviceconfig.Duration(30 * time.Second),
   208  							MaxEjectionTime:    iserviceconfig.Duration(300 * time.Second),
   209  							MaxEjectionPercent: 10,
   210  							// sre and fpe are both nil
   211  						},
   212  					},
   213  				},
   214  				xdsLBPolicy: iserviceconfig.BalancerConfig{ // do we want to make this not pointer
   215  					Name:   roundrobin.Name,
   216  					Config: nil,
   217  				},
   218  			},
   219  			wantErr: false,
   220  		},
   221  		{
   222  			name: "OK with multiple discovery mechanisms",
   223  			js:   testJSONConfig2,
   224  			want: &LBConfig{
   225  				DiscoveryMechanisms: []DiscoveryMechanism{
   226  					{
   227  						Cluster:               testClusterName,
   228  						LoadReportingServer:   testLRSServerConfig,
   229  						MaxConcurrentRequests: newUint32(testMaxRequests),
   230  						Type:                  DiscoveryMechanismTypeEDS,
   231  						EDSServiceName:        testEDSService,
   232  						outlierDetection: outlierdetection.LBConfig{
   233  							Interval:           iserviceconfig.Duration(10 * time.Second), // default interval
   234  							BaseEjectionTime:   iserviceconfig.Duration(30 * time.Second),
   235  							MaxEjectionTime:    iserviceconfig.Duration(300 * time.Second),
   236  							MaxEjectionPercent: 10,
   237  							// sre and fpe are both nil
   238  						},
   239  					},
   240  					{
   241  						Type: DiscoveryMechanismTypeLogicalDNS,
   242  						outlierDetection: outlierdetection.LBConfig{
   243  							Interval:           iserviceconfig.Duration(10 * time.Second), // default interval
   244  							BaseEjectionTime:   iserviceconfig.Duration(30 * time.Second),
   245  							MaxEjectionTime:    iserviceconfig.Duration(300 * time.Second),
   246  							MaxEjectionPercent: 10,
   247  							// sre and fpe are both nil
   248  						},
   249  					},
   250  				},
   251  				xdsLBPolicy: iserviceconfig.BalancerConfig{
   252  					Name:   roundrobin.Name,
   253  					Config: nil,
   254  				},
   255  			},
   256  			wantErr: false,
   257  		},
   258  		{
   259  			name: "OK with picking policy round_robin",
   260  			js:   testJSONConfig3,
   261  			want: &LBConfig{
   262  				DiscoveryMechanisms: []DiscoveryMechanism{
   263  					{
   264  						Cluster:               testClusterName,
   265  						LoadReportingServer:   testLRSServerConfig,
   266  						MaxConcurrentRequests: newUint32(testMaxRequests),
   267  						Type:                  DiscoveryMechanismTypeEDS,
   268  						EDSServiceName:        testEDSService,
   269  						outlierDetection: outlierdetection.LBConfig{
   270  							Interval:           iserviceconfig.Duration(10 * time.Second), // default interval
   271  							BaseEjectionTime:   iserviceconfig.Duration(30 * time.Second),
   272  							MaxEjectionTime:    iserviceconfig.Duration(300 * time.Second),
   273  							MaxEjectionPercent: 10,
   274  							// sre and fpe are both nil
   275  						},
   276  					},
   277  				},
   278  				xdsLBPolicy: iserviceconfig.BalancerConfig{
   279  					Name:   roundrobin.Name,
   280  					Config: nil,
   281  				},
   282  			},
   283  			wantErr: false,
   284  		},
   285  		{
   286  			name: "OK with picking policy ring_hash",
   287  			js:   testJSONConfig4,
   288  			want: &LBConfig{
   289  				DiscoveryMechanisms: []DiscoveryMechanism{
   290  					{
   291  						Cluster:               testClusterName,
   292  						LoadReportingServer:   testLRSServerConfig,
   293  						MaxConcurrentRequests: newUint32(testMaxRequests),
   294  						Type:                  DiscoveryMechanismTypeEDS,
   295  						EDSServiceName:        testEDSService,
   296  						outlierDetection: outlierdetection.LBConfig{
   297  							Interval:           iserviceconfig.Duration(10 * time.Second), // default interval
   298  							BaseEjectionTime:   iserviceconfig.Duration(30 * time.Second),
   299  							MaxEjectionTime:    iserviceconfig.Duration(300 * time.Second),
   300  							MaxEjectionPercent: 10,
   301  							// sre and fpe are both nil
   302  						},
   303  					},
   304  				},
   305  				xdsLBPolicy: iserviceconfig.BalancerConfig{
   306  					Name:   ringhash.Name,
   307  					Config: &ringhash.LBConfig{MinRingSize: 1024, MaxRingSize: 4096}, // Ringhash LB config with default min and max.
   308  				},
   309  			},
   310  			wantErr: false,
   311  		},
   312  		{
   313  			name: "noop-outlier-detection",
   314  			js:   testJSONConfig5,
   315  			want: &LBConfig{
   316  				DiscoveryMechanisms: []DiscoveryMechanism{
   317  					{
   318  						Cluster:               testClusterName,
   319  						LoadReportingServer:   testLRSServerConfig,
   320  						MaxConcurrentRequests: newUint32(testMaxRequests),
   321  						Type:                  DiscoveryMechanismTypeEDS,
   322  						EDSServiceName:        testEDSService,
   323  						outlierDetection: outlierdetection.LBConfig{
   324  							Interval:           iserviceconfig.Duration(10 * time.Second), // default interval
   325  							BaseEjectionTime:   iserviceconfig.Duration(30 * time.Second),
   326  							MaxEjectionTime:    iserviceconfig.Duration(300 * time.Second),
   327  							MaxEjectionPercent: 10,
   328  							// sre and fpe are both nil
   329  						},
   330  					},
   331  				},
   332  				xdsLBPolicy: iserviceconfig.BalancerConfig{
   333  					Name:   roundrobin.Name,
   334  					Config: nil,
   335  				},
   336  			},
   337  			wantErr: false,
   338  		},
   339  	}
   340  	for _, tt := range tests {
   341  		b := balancer.Get(Name)
   342  		if b == nil {
   343  			t.Fatalf("LB policy %q not registered", Name)
   344  		}
   345  		cfgParser, ok := b.(balancer.ConfigParser)
   346  		if !ok {
   347  			t.Fatalf("LB policy %q does not support config parsing", Name)
   348  		}
   349  		t.Run(tt.name, func(t *testing.T) {
   350  			got, err := cfgParser.ParseConfig([]byte(tt.js))
   351  			if (err != nil) != tt.wantErr {
   352  				t.Fatalf("parseConfig() error = %v, wantErr %v", err, tt.wantErr)
   353  			}
   354  			if tt.wantErr {
   355  				return
   356  			}
   357  			if diff := cmp.Diff(got, tt.want, cmp.AllowUnexported(LBConfig{}), cmpopts.IgnoreFields(LBConfig{}, "XDSLBPolicy")); diff != "" {
   358  				t.Errorf("parseConfig() got unexpected output, diff (-got +want): %v", diff)
   359  			}
   360  		})
   361  	}
   362  }
   363  
   364  func newUint32(i uint32) *uint32 {
   365  	return &i
   366  }
   367  

View as plain text