1// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package httptypes
16
17import (
18	"encoding/json"
19	"net/url"
20	"reflect"
21	"testing"
22
23	"go.etcd.io/etcd/pkg/types"
24)
25
26func TestMemberUnmarshal(t *testing.T) {
27	tests := []struct {
28		body       []byte
29		wantMember Member
30		wantError  bool
31	}{
32		// no URLs, just check ID & Name
33		{
34			body:       []byte(`{"id": "c", "name": "dungarees"}`),
35			wantMember: Member{ID: "c", Name: "dungarees", PeerURLs: nil, ClientURLs: nil},
36		},
37
38		// both client and peer URLs
39		{
40			body: []byte(`{"peerURLs": ["http://127.0.0.1:2379"], "clientURLs": ["http://127.0.0.1:2379"]}`),
41			wantMember: Member{
42				PeerURLs: []string{
43					"http://127.0.0.1:2379",
44				},
45				ClientURLs: []string{
46					"http://127.0.0.1:2379",
47				},
48			},
49		},
50
51		// multiple peer URLs
52		{
53			body: []byte(`{"peerURLs": ["http://127.0.0.1:2379", "https://example.com"]}`),
54			wantMember: Member{
55				PeerURLs: []string{
56					"http://127.0.0.1:2379",
57					"https://example.com",
58				},
59				ClientURLs: nil,
60			},
61		},
62
63		// multiple client URLs
64		{
65			body: []byte(`{"clientURLs": ["http://127.0.0.1:2379", "https://example.com"]}`),
66			wantMember: Member{
67				PeerURLs: nil,
68				ClientURLs: []string{
69					"http://127.0.0.1:2379",
70					"https://example.com",
71				},
72			},
73		},
74
75		// invalid JSON
76		{
77			body:      []byte(`{"peerU`),
78			wantError: true,
79		},
80	}
81
82	for i, tt := range tests {
83		got := Member{}
84		err := json.Unmarshal(tt.body, &got)
85		if tt.wantError != (err != nil) {
86			t.Errorf("#%d: want error %t, got %v", i, tt.wantError, err)
87			continue
88		}
89
90		if !reflect.DeepEqual(tt.wantMember, got) {
91			t.Errorf("#%d: incorrect output: want=%#v, got=%#v", i, tt.wantMember, got)
92		}
93	}
94}
95
96func TestMemberCreateRequestUnmarshal(t *testing.T) {
97	body := []byte(`{"peerURLs": ["http://127.0.0.1:8081", "https://127.0.0.1:8080"]}`)
98	want := MemberCreateRequest{
99		PeerURLs: types.URLs([]url.URL{
100			{Scheme: "http", Host: "127.0.0.1:8081"},
101			{Scheme: "https", Host: "127.0.0.1:8080"},
102		}),
103	}
104
105	var req MemberCreateRequest
106	if err := json.Unmarshal(body, &req); err != nil {
107		t.Fatalf("Unmarshal returned unexpected err=%v", err)
108	}
109
110	if !reflect.DeepEqual(want, req) {
111		t.Fatalf("Failed to unmarshal MemberCreateRequest: want=%#v, got=%#v", want, req)
112	}
113}
114
115func TestMemberCreateRequestUnmarshalFail(t *testing.T) {
116	tests := [][]byte{
117		// invalid JSON
118		[]byte(``),
119		[]byte(`{`),
120
121		// spot-check validation done in types.NewURLs
122		[]byte(`{"peerURLs": "foo"}`),
123		[]byte(`{"peerURLs": ["."]}`),
124		[]byte(`{"peerURLs": []}`),
125		[]byte(`{"peerURLs": ["http://127.0.0.1:2379/foo"]}`),
126		[]byte(`{"peerURLs": ["http://127.0.0.1"]}`),
127	}
128
129	for i, tt := range tests {
130		var req MemberCreateRequest
131		if err := json.Unmarshal(tt, &req); err == nil {
132			t.Errorf("#%d: expected err, got nil", i)
133		}
134	}
135}
136