Merge pull request #122356 from my-git9/ut-etcd-32
kubeadm: increase ut coverage for util/etcd
This commit is contained in:
		| @@ -104,6 +104,8 @@ type Client struct { | ||||
| 	Endpoints []string | ||||
|  | ||||
| 	newEtcdClient func(endpoints []string) (etcdClient, error) | ||||
|  | ||||
| 	listMembersFunc func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) | ||||
| } | ||||
|  | ||||
| // New creates a new EtcdCluster client | ||||
| @@ -135,6 +137,8 @@ func New(endpoints []string, ca, cert, key string) (*Client, error) { | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	client.listMembersFunc = client.listMembers | ||||
|  | ||||
| 	return &client, nil | ||||
| } | ||||
|  | ||||
| @@ -274,11 +278,14 @@ type Member struct { | ||||
| 	PeerURL string | ||||
| } | ||||
|  | ||||
| func (c *Client) listMembers() (*clientv3.MemberListResponse, error) { | ||||
| func (c *Client) listMembers(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) { | ||||
| 	// Gets the member list | ||||
| 	var lastError error | ||||
| 	var resp *clientv3.MemberListResponse | ||||
| 	err := wait.ExponentialBackoff(etcdBackoff, func() (bool, error) { | ||||
| 	if backoff == nil { | ||||
| 		backoff = &etcdBackoff | ||||
| 	} | ||||
| 	err := wait.ExponentialBackoff(*backoff, func() (bool, error) { | ||||
| 		cli, err := c.newEtcdClient(c.Endpoints) | ||||
| 		if err != nil { | ||||
| 			lastError = err | ||||
| @@ -304,7 +311,7 @@ func (c *Client) listMembers() (*clientv3.MemberListResponse, error) { | ||||
|  | ||||
| // GetMemberID returns the member ID of the given peer URL | ||||
| func (c *Client) GetMemberID(peerURL string) (uint64, error) { | ||||
| 	resp, err := c.listMembers() | ||||
| 	resp, err := c.listMembersFunc(nil) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| @@ -319,7 +326,7 @@ func (c *Client) GetMemberID(peerURL string) (uint64, error) { | ||||
|  | ||||
| // ListMembers returns the member list. | ||||
| func (c *Client) ListMembers() ([]Member, error) { | ||||
| 	resp, err := c.listMembers() | ||||
| 	resp, err := c.listMembersFunc(nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -480,7 +487,7 @@ func (c *Client) addMember(name string, peerAddrs string, isLearner bool) ([]Mem | ||||
|  | ||||
| // isLearner returns true if the given member ID is a learner. | ||||
| func (c *Client) isLearner(memberID uint64) (bool, error) { | ||||
| 	resp, err := c.listMembers() | ||||
| 	resp, err := c.listMembersFunc(nil) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
|   | ||||
| @@ -482,6 +482,11 @@ func TestClient_GetMemberID(t *testing.T) { | ||||
| 				Endpoints:     tt.fields.Endpoints, | ||||
| 				newEtcdClient: tt.fields.newEtcdClient, | ||||
| 			} | ||||
| 			c.listMembersFunc = func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) { | ||||
| 				f, _ := c.newEtcdClient([]string{}) | ||||
| 				resp, _ := f.MemberList(context.TODO()) | ||||
| 				return resp, nil | ||||
| 			} | ||||
|  | ||||
| 			got, err := c.GetMemberID(tt.args.peerURL) | ||||
| 			if !errors.Is(tt.wantErr, err) { | ||||
| @@ -494,3 +499,292 @@ func TestClient_GetMemberID(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestListMembers(t *testing.T) { | ||||
| 	type fields struct { | ||||
| 		Endpoints       []string | ||||
| 		newEtcdClient   func(endpoints []string) (etcdClient, error) | ||||
| 		listMembersFunc func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) | ||||
| 	} | ||||
| 	tests := []struct { | ||||
| 		name      string | ||||
| 		fields    fields | ||||
| 		want      []Member | ||||
| 		wantError bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name: "PeerURLs are empty", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 			}, | ||||
| 			want: []Member{}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "PeerURLs are non-empty", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{ | ||||
| 							{ | ||||
| 								ID:   1, | ||||
| 								Name: "member1", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member1:2380", | ||||
| 								}, | ||||
| 							}, | ||||
| 							{ | ||||
| 								ID:   2, | ||||
| 								Name: "member2", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member2:2380", | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 			}, | ||||
| 			want: []Member{ | ||||
| 				{ | ||||
| 					Name:    "member1", | ||||
| 					PeerURL: "https://member1:2380", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:    "member2", | ||||
| 					PeerURL: "https://member2:2380", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "PeerURLs has multiple urls", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{ | ||||
| 							{ | ||||
| 								ID:   1, | ||||
| 								Name: "member1", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member1:2380", | ||||
| 									"https://member2:2380", | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 			}, | ||||
| 			want: []Member{ | ||||
| 				{ | ||||
| 					Name:    "member1", | ||||
| 					PeerURL: "https://member1:2380", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "ListMembers return error", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{ | ||||
| 							{ | ||||
| 								ID:   1, | ||||
| 								Name: "member1", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member1:2380", | ||||
| 									"https://member2:2380", | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 				listMembersFunc: func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) { | ||||
| 					return nil, errNotImplemented | ||||
| 				}, | ||||
| 			}, | ||||
| 			want:      nil, | ||||
| 			wantError: true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tt := range tests { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
| 			c := &Client{ | ||||
| 				Endpoints:       tt.fields.Endpoints, | ||||
| 				newEtcdClient:   tt.fields.newEtcdClient, | ||||
| 				listMembersFunc: tt.fields.listMembersFunc, | ||||
| 			} | ||||
| 			if c.listMembersFunc == nil { | ||||
| 				c.listMembersFunc = func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) { | ||||
| 					return c.listMembers(&wait.Backoff{Steps: 1}) | ||||
| 				} | ||||
| 			} | ||||
| 			got, err := c.ListMembers() | ||||
| 			if !reflect.DeepEqual(got, tt.want) { | ||||
| 				t.Errorf("ListMembers() = %v, want %v", got, tt.want) | ||||
| 			} | ||||
| 			if (err != nil) != (tt.wantError) { | ||||
| 				t.Errorf("ListMembers() error = %v, wantError %v", err, tt.wantError) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestIsLearner(t *testing.T) { | ||||
| 	type fields struct { | ||||
| 		Endpoints       []string | ||||
| 		newEtcdClient   func(endpoints []string) (etcdClient, error) | ||||
| 		listMembersFunc func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) | ||||
| 	} | ||||
| 	tests := []struct { | ||||
| 		name      string | ||||
| 		fields    fields | ||||
| 		memberID  uint64 | ||||
| 		want      bool | ||||
| 		wantError bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name: "The specified member is not a learner", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{ | ||||
| 							{ | ||||
| 								ID:   1, | ||||
| 								Name: "member1", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member1:2380", | ||||
| 								}, | ||||
| 								IsLearner: false, | ||||
| 							}, | ||||
| 						}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 			}, | ||||
| 			memberID: 1, | ||||
| 			want:     false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "The specified member is a learner", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{ | ||||
| 							{ | ||||
| 								ID:   1, | ||||
| 								Name: "member1", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member1:2380", | ||||
| 								}, | ||||
| 								IsLearner: true, | ||||
| 							}, | ||||
| 							{ | ||||
| 								ID:   2, | ||||
| 								Name: "member2", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member2:2380", | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 			}, | ||||
| 			memberID: 1, | ||||
| 			want:     true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "The specified member does not exist", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 			}, | ||||
| 			memberID: 3, | ||||
| 			want:     false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "Learner ID is empty", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{ | ||||
| 							{ | ||||
| 								Name: "member2", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member2:2380", | ||||
| 								}, | ||||
| 								IsLearner: true, | ||||
| 							}, | ||||
| 						}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 			}, | ||||
| 			want: true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "ListMembers returns an error", | ||||
| 			fields: fields{ | ||||
| 				Endpoints: []string{}, | ||||
| 				newEtcdClient: func(endpoints []string) (etcdClient, error) { | ||||
| 					f := &fakeEtcdClient{ | ||||
| 						members: []*pb.Member{ | ||||
| 							{ | ||||
| 								Name: "member2", | ||||
| 								PeerURLs: []string{ | ||||
| 									"https://member2:2380", | ||||
| 								}, | ||||
| 								IsLearner: true, | ||||
| 							}, | ||||
| 						}, | ||||
| 					} | ||||
| 					return f, nil | ||||
| 				}, | ||||
| 				listMembersFunc: func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) { | ||||
| 					return nil, errNotImplemented | ||||
| 				}, | ||||
| 			}, | ||||
| 			want:      false, | ||||
| 			wantError: true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tt := range tests { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
| 			c := &Client{ | ||||
| 				Endpoints:       tt.fields.Endpoints, | ||||
| 				newEtcdClient:   tt.fields.newEtcdClient, | ||||
| 				listMembersFunc: tt.fields.listMembersFunc, | ||||
| 			} | ||||
| 			if c.listMembersFunc == nil { | ||||
| 				c.listMembersFunc = func(backoff *wait.Backoff) (*clientv3.MemberListResponse, error) { | ||||
| 					f, _ := c.newEtcdClient([]string{}) | ||||
| 					resp, _ := f.MemberList(context.TODO()) | ||||
| 					return resp, nil | ||||
| 				} | ||||
| 			} | ||||
| 			got, err := c.isLearner(tt.memberID) | ||||
| 			if got != tt.want { | ||||
| 				t.Errorf("isLearner() = %v, want %v", got, tt.want) | ||||
| 			} | ||||
| 			if (err != nil) != (tt.wantError) { | ||||
| 				t.Errorf("isLearner() error = %v, wantError %v", err, tt.wantError) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot