540 lines
20 KiB
Go
540 lines
20 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package channelparticipation_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
|
|
"github.com/hyperledger/fabric-protos-go/common"
|
|
"github.com/hyperledger/fabric/orderer/common/channelparticipation"
|
|
"github.com/hyperledger/fabric/orderer/common/channelparticipation/mocks"
|
|
"github.com/hyperledger/fabric/orderer/common/localconfig"
|
|
"github.com/hyperledger/fabric/orderer/common/types"
|
|
"github.com/hyperledger/fabric/protoutil"
|
|
"github.com/pkg/errors"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewHTTPHandler(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{
|
|
Enabled: false,
|
|
}
|
|
h := channelparticipation.NewHTTPHandler(config, &mocks.ChannelManagement{})
|
|
require.NotNilf(t, h, "cannot create handler")
|
|
}
|
|
|
|
func TestHTTPHandler_ServeHTTP_Disabled(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{Enabled: false}
|
|
_, h := setup(config, t)
|
|
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", channelparticipation.URLBaseV1, nil)
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusServiceUnavailable, "channel participation API is disabled", resp)
|
|
}
|
|
|
|
func TestHTTPHandler_ServeHTTP_InvalidMethods(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{Enabled: true}
|
|
_, h := setup(config, t)
|
|
invalidMethods := []string{http.MethodConnect, http.MethodHead, http.MethodOptions, http.MethodPatch, http.MethodPut, http.MethodTrace}
|
|
|
|
t.Run("on /channels/ch-id", func(t *testing.T) {
|
|
invalidMethodsExt := append(invalidMethods, http.MethodPost)
|
|
for _, method := range invalidMethodsExt {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(method, path.Join(channelparticipation.URLBaseV1Channels, "ch-id"), nil)
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusMethodNotAllowed, fmt.Sprintf("invalid request method: %s", method), resp)
|
|
require.Equal(t, "GET, DELETE", resp.Result().Header.Get("Allow"), "%s", method)
|
|
}
|
|
})
|
|
|
|
t.Run("on /channels", func(t *testing.T) {
|
|
invalidMethodsExt := append(invalidMethods, http.MethodDelete)
|
|
for _, method := range invalidMethodsExt {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(method, channelparticipation.URLBaseV1Channels, nil)
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusMethodNotAllowed, fmt.Sprintf("invalid request method: %s", method), resp)
|
|
require.Equal(t, "GET, POST", resp.Result().Header.Get("Allow"), "%s", method)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestHTTPHandler_ServeHTTP_ListErrors(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{Enabled: true}
|
|
_, h := setup(config, t)
|
|
|
|
t.Run("bad base", func(t *testing.T) {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/oops", nil)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusNotFound, resp.Result().StatusCode)
|
|
})
|
|
|
|
t.Run("bad resource", func(t *testing.T) {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1+"oops", nil)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusNotFound, resp.Result().StatusCode)
|
|
})
|
|
|
|
t.Run("bad channel ID", func(t *testing.T) {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels+"/no/slash", nil)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusNotFound, resp.Result().StatusCode)
|
|
})
|
|
|
|
t.Run("illegal character in channel ID", func(t *testing.T) {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels+"/Oops", nil)
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "invalid channel ID: 'Oops' contains illegal characters", resp)
|
|
})
|
|
|
|
t.Run("bad Accept header", func(t *testing.T) {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels+"/ok", nil)
|
|
req.Header.Set("Accept", "text/html")
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusNotAcceptable, "response Content-Type is application/json only", resp)
|
|
})
|
|
}
|
|
|
|
func TestHTTPHandler_ServeHTTP_ListAll(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{Enabled: true}
|
|
fakeManager, h := setup(config, t)
|
|
|
|
t.Run("two channels", func(t *testing.T) {
|
|
list := types.ChannelList{
|
|
Channels: []types.ChannelInfoShort{
|
|
{Name: "app-channel1", URL: ""},
|
|
{Name: "app-channel2", URL: ""},
|
|
},
|
|
SystemChannel: &types.ChannelInfoShort{Name: "system-channel", URL: ""},
|
|
}
|
|
fakeManager.ChannelListReturns(list)
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels, nil)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusOK, resp.Result().StatusCode)
|
|
require.Equal(t, "application/json", resp.Result().Header.Get("Content-Type"))
|
|
require.Equal(t, "no-store", resp.Result().Header.Get("Cache-Control"))
|
|
|
|
listAll := &types.ChannelList{}
|
|
err := json.Unmarshal(resp.Body.Bytes(), listAll)
|
|
require.NoError(t, err, "cannot be unmarshaled")
|
|
require.Equal(t, 2, len(listAll.Channels))
|
|
require.Equal(t, list.SystemChannel, listAll.SystemChannel)
|
|
m := make(map[string]bool)
|
|
for _, item := range listAll.Channels {
|
|
m[item.Name] = true
|
|
require.Equal(t, channelparticipation.URLBaseV1Channels+"/"+item.Name, item.URL)
|
|
}
|
|
require.True(t, m["app-channel1"])
|
|
require.True(t, m["app-channel2"])
|
|
})
|
|
|
|
t.Run("no channels, empty channels", func(t *testing.T) {
|
|
list := types.ChannelList{
|
|
Channels: []types.ChannelInfoShort{},
|
|
}
|
|
fakeManager.ChannelListReturns(list)
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels, nil)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusOK, resp.Result().StatusCode)
|
|
require.Equal(t, "application/json", resp.Result().Header.Get("Content-Type"))
|
|
require.Equal(t, "no-store", resp.Result().Header.Get("Cache-Control"))
|
|
|
|
listAll := &types.ChannelList{}
|
|
err := json.Unmarshal(resp.Body.Bytes(), listAll)
|
|
require.NoError(t, err, "cannot be unmarshaled")
|
|
require.Equal(t, 0, len(listAll.Channels))
|
|
require.NotNil(t, listAll.Channels)
|
|
require.Nil(t, listAll.SystemChannel)
|
|
})
|
|
|
|
t.Run("no channels, Accept ok", func(t *testing.T) {
|
|
list := types.ChannelList{}
|
|
fakeManager.ChannelListReturns(list)
|
|
|
|
for _, accept := range []string{"application/json", "application/*", "*/*"} {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels, nil)
|
|
req.Header.Set("Accept", accept)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusOK, resp.Result().StatusCode, "Accept: %s", accept)
|
|
require.Equal(t, "application/json", resp.Result().Header.Get("Content-Type"))
|
|
require.Equal(t, "no-store", resp.Result().Header.Get("Cache-Control"))
|
|
|
|
listAll := &types.ChannelList{}
|
|
err := json.Unmarshal(resp.Body.Bytes(), listAll)
|
|
require.NoError(t, err, "cannot be unmarshaled")
|
|
require.Equal(t, 0, len(listAll.Channels))
|
|
require.Nil(t, listAll.Channels)
|
|
require.Nil(t, listAll.SystemChannel)
|
|
}
|
|
})
|
|
|
|
t.Run("redirect from base V1 URL", func(t *testing.T) {
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1, nil)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusFound, resp.Result().StatusCode)
|
|
require.Equal(t, channelparticipation.URLBaseV1Channels, resp.Result().Header.Get("Location"))
|
|
})
|
|
}
|
|
|
|
func TestHTTPHandler_ServeHTTP_ListSingle(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{Enabled: true}
|
|
fakeManager, h := setup(config, t)
|
|
require.NotNilf(t, h, "cannot create handler")
|
|
|
|
t.Run("channel exists", func(t *testing.T) {
|
|
fakeManager.ChannelInfoReturns(types.ChannelInfo{
|
|
Name: "app-channel",
|
|
ConsensusRelation: "consenter",
|
|
Status: "active",
|
|
Height: 3,
|
|
}, nil)
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels+"/app-channel", nil)
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusOK, resp.Result().StatusCode)
|
|
require.Equal(t, "application/json", resp.Result().Header.Get("Content-Type"))
|
|
require.Equal(t, "no-store", resp.Result().Header.Get("Cache-Control"))
|
|
|
|
infoResp := types.ChannelInfo{}
|
|
err := json.Unmarshal(resp.Body.Bytes(), &infoResp)
|
|
require.NoError(t, err, "cannot be unmarshaled")
|
|
require.Equal(t, types.ChannelInfo{
|
|
Name: "app-channel",
|
|
URL: channelparticipation.URLBaseV1Channels + "/app-channel",
|
|
ConsensusRelation: "consenter",
|
|
Status: "active",
|
|
Height: 3,
|
|
}, infoResp)
|
|
})
|
|
|
|
t.Run("channel does not exists", func(t *testing.T) {
|
|
fakeManager.ChannelInfoReturns(types.ChannelInfo{}, errors.New("not found"))
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, channelparticipation.URLBaseV1Channels+"/app-channel", nil)
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusNotFound, "not found", resp)
|
|
})
|
|
}
|
|
|
|
func TestHTTPHandler_ServeHTTP_Join(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{
|
|
Enabled: true,
|
|
MaxRequestBodySize: 1024 * 1024,
|
|
}
|
|
|
|
t.Run("created ok", func(t *testing.T) {
|
|
fakeManager, h := setup(config, t)
|
|
fakeManager.JoinChannelReturns(types.ChannelInfo{
|
|
Name: "app-channel",
|
|
ConsensusRelation: "consenter",
|
|
Status: "active",
|
|
Height: 1,
|
|
}, nil)
|
|
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, validBlockBytes("ch-id"))
|
|
h.ServeHTTP(resp, req)
|
|
require.Equal(t, http.StatusCreated, resp.Result().StatusCode)
|
|
require.Equal(t, "application/json", resp.Result().Header.Get("Content-Type"))
|
|
|
|
infoResp := types.ChannelInfo{}
|
|
err := json.Unmarshal(resp.Body.Bytes(), &infoResp)
|
|
require.NoError(t, err, "cannot be unmarshaled")
|
|
require.Equal(t, types.ChannelInfo{
|
|
Name: "app-channel",
|
|
URL: channelparticipation.URLBaseV1Channels + "/app-channel",
|
|
ConsensusRelation: "consenter",
|
|
Status: "active",
|
|
Height: 1,
|
|
}, infoResp)
|
|
})
|
|
|
|
t.Run("Error: system channel not supported", func(t *testing.T) {
|
|
_, h := setup(config, t)
|
|
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, sysChanBlockBytes("ch-id"))
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "invalid join block: invalid config: contains consortiums: system channel not supported", resp)
|
|
})
|
|
|
|
t.Run("Error: Channel Exists", func(t *testing.T) {
|
|
fakeManager, h := setup(config, t)
|
|
fakeManager.JoinChannelReturns(types.ChannelInfo{}, types.ErrChannelAlreadyExists)
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, validBlockBytes("ch-id"))
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusMethodNotAllowed, "cannot join: channel already exists", resp)
|
|
require.Equal(t, "GET, DELETE", resp.Result().Header.Get("Allow"))
|
|
})
|
|
|
|
t.Run("Error: App Channels Exist", func(t *testing.T) {
|
|
fakeManager, h := setup(config, t)
|
|
fakeManager.JoinChannelReturns(types.ChannelInfo{}, types.ErrAppChannelsAlreadyExists)
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, validBlockBytes("ch-id"))
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusForbidden, "cannot join: application channels already exist", resp)
|
|
})
|
|
|
|
t.Run("Error: Channel Pending Removal", func(t *testing.T) {
|
|
fakeManager, h := setup(config, t)
|
|
fakeManager.JoinChannelReturns(types.ChannelInfo{}, types.ErrChannelPendingRemoval)
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, validBlockBytes("ch-id"))
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusConflict, "cannot join: channel pending removal", resp)
|
|
})
|
|
|
|
t.Run("bad body - not a block", func(t *testing.T) {
|
|
_, h := setup(config, t)
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, []byte{1, 2, 3, 4})
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "cannot unmarshal file part config-block into a block", resp)
|
|
})
|
|
|
|
t.Run("bad body - invalid join block", func(t *testing.T) {
|
|
_, h := setup(config, t)
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, []byte{})
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "invalid join block: block is not a config block", resp)
|
|
})
|
|
|
|
t.Run("content type mismatch", func(t *testing.T) {
|
|
_, h := setup(config, t)
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodPost, channelparticipation.URLBaseV1Channels, nil)
|
|
req.Header.Set("Content-Type", "text/plain")
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "unsupported Content-Type: [text/plain]", resp)
|
|
})
|
|
|
|
t.Run("form-data: bad form - no boundary", func(t *testing.T) {
|
|
_, h := setup(config, t)
|
|
resp := httptest.NewRecorder()
|
|
|
|
joinBody := new(bytes.Buffer)
|
|
writer := multipart.NewWriter(joinBody)
|
|
part, err := writer.CreateFormFile(channelparticipation.FormDataConfigBlockKey, "join-config.block")
|
|
require.NoError(t, err)
|
|
part.Write([]byte{})
|
|
err = writer.Close()
|
|
require.NoError(t, err)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, channelparticipation.URLBaseV1Channels, joinBody)
|
|
req.Header.Set("Content-Type", "multipart/form-data") // missing boundary
|
|
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "cannot read form from request body: multipart: boundary is empty", resp)
|
|
})
|
|
|
|
t.Run("form-data: bad form - no key", func(t *testing.T) {
|
|
_, h := setup(config, t)
|
|
resp := httptest.NewRecorder()
|
|
|
|
joinBody := new(bytes.Buffer)
|
|
writer := multipart.NewWriter(joinBody)
|
|
part, err := writer.CreateFormFile("bad-key", "join-config.block")
|
|
require.NoError(t, err)
|
|
part.Write([]byte{})
|
|
err = writer.Close()
|
|
require.NoError(t, err)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, channelparticipation.URLBaseV1Channels, joinBody)
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "form does not contains part key: config-block", resp)
|
|
})
|
|
|
|
t.Run("form-data: bad form - too many parts", func(t *testing.T) {
|
|
_, h := setup(config, t)
|
|
resp := httptest.NewRecorder()
|
|
|
|
joinBody := new(bytes.Buffer)
|
|
writer := multipart.NewWriter(joinBody)
|
|
part, err := writer.CreateFormFile(channelparticipation.FormDataConfigBlockKey, "join-config.block")
|
|
require.NoError(t, err)
|
|
part.Write([]byte{})
|
|
part, err = writer.CreateFormField("not-wanted")
|
|
require.NoError(t, err)
|
|
part.Write([]byte("something"))
|
|
err = writer.Close()
|
|
require.NoError(t, err)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, channelparticipation.URLBaseV1Channels, joinBody)
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "form contains too many parts", resp)
|
|
})
|
|
|
|
t.Run("body larger that MaxRequestBodySize", func(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{
|
|
Enabled: true,
|
|
MaxRequestBodySize: 1,
|
|
}
|
|
_, h := setup(config, t)
|
|
resp := httptest.NewRecorder()
|
|
req := genJoinRequestFormData(t, []byte{1, 2, 3, 4})
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusBadRequest, "cannot read form from request body: multipart: NextPart: http: request body too large", resp)
|
|
})
|
|
}
|
|
|
|
func TestHTTPHandler_ServeHTTP_Remove(t *testing.T) {
|
|
config := localconfig.ChannelParticipation{Enabled: true}
|
|
fakeManager, h := setup(config, t)
|
|
|
|
type testDef struct {
|
|
name string
|
|
channel string
|
|
fakeReturns error
|
|
expectedCode int
|
|
expectedErr error
|
|
}
|
|
|
|
testCases := []testDef{
|
|
{
|
|
name: "success",
|
|
channel: "my-channel",
|
|
fakeReturns: nil,
|
|
expectedCode: http.StatusNoContent,
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
name: "bad channel ID",
|
|
channel: "My-Channel",
|
|
fakeReturns: nil,
|
|
expectedCode: http.StatusBadRequest,
|
|
expectedErr: errors.New("invalid channel ID: 'My-Channel' contains illegal characters"),
|
|
},
|
|
{
|
|
name: "channel does not exist",
|
|
channel: "my-channel",
|
|
fakeReturns: types.ErrChannelNotExist,
|
|
expectedCode: http.StatusNotFound,
|
|
expectedErr: errors.Wrap(types.ErrChannelNotExist, "cannot remove"),
|
|
},
|
|
{
|
|
name: "some other error",
|
|
channel: "my-channel",
|
|
fakeReturns: os.ErrInvalid,
|
|
expectedCode: http.StatusBadRequest,
|
|
expectedErr: errors.Wrap(os.ErrInvalid, "cannot remove"),
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
fakeManager.RemoveChannelReturns(testCase.fakeReturns)
|
|
resp := httptest.NewRecorder()
|
|
target := path.Join(channelparticipation.URLBaseV1Channels, testCase.channel)
|
|
req := httptest.NewRequest(http.MethodDelete, target, nil)
|
|
h.ServeHTTP(resp, req)
|
|
|
|
if testCase.expectedErr == nil {
|
|
require.Equal(t, testCase.expectedCode, resp.Result().StatusCode)
|
|
require.Equal(t, 0, resp.Body.Len(), "empty body")
|
|
} else {
|
|
checkErrorResponse(t, testCase.expectedCode, testCase.expectedErr.Error(), resp)
|
|
}
|
|
})
|
|
}
|
|
|
|
t.Run("Error: System Channel Exists", func(t *testing.T) {
|
|
fakeManager, h := setup(config, t)
|
|
fakeManager.RemoveChannelReturns(types.ErrSystemChannelExists)
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodDelete, path.Join(channelparticipation.URLBaseV1Channels, "my-channel"), nil)
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusMethodNotAllowed, "cannot remove: system channel exists", resp)
|
|
require.Equal(t, "GET", resp.Result().Header.Get("Allow"))
|
|
})
|
|
|
|
t.Run("Error: Channel Pending Removal", func(t *testing.T) {
|
|
fakeManager, h := setup(config, t)
|
|
fakeManager.RemoveChannelReturns(types.ErrChannelPendingRemoval)
|
|
resp := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodDelete, path.Join(channelparticipation.URLBaseV1Channels, "my-channel"), nil)
|
|
h.ServeHTTP(resp, req)
|
|
checkErrorResponse(t, http.StatusConflict, "cannot remove: channel pending removal", resp)
|
|
})
|
|
}
|
|
|
|
func setup(config localconfig.ChannelParticipation, t *testing.T) (*mocks.ChannelManagement, *channelparticipation.HTTPHandler) {
|
|
fakeManager := &mocks.ChannelManagement{}
|
|
h := channelparticipation.NewHTTPHandler(config, fakeManager)
|
|
require.NotNilf(t, h, "cannot create handler")
|
|
return fakeManager, h
|
|
}
|
|
|
|
func checkErrorResponse(t *testing.T, expectedCode int, expectedErrMsg string, resp *httptest.ResponseRecorder) {
|
|
require.Equal(t, expectedCode, resp.Result().StatusCode)
|
|
|
|
headerArray, headerOK := resp.Result().Header["Content-Type"]
|
|
require.True(t, headerOK)
|
|
require.Len(t, headerArray, 1)
|
|
require.Equal(t, "application/json", headerArray[0])
|
|
|
|
decoder := json.NewDecoder(resp.Body)
|
|
respErr := &types.ErrorResponse{}
|
|
err := decoder.Decode(respErr)
|
|
require.NoError(t, err, "body: %s", resp.Body.String())
|
|
require.Contains(t, respErr.Error, expectedErrMsg)
|
|
}
|
|
|
|
func genJoinRequestFormData(t *testing.T, blockBytes []byte) *http.Request {
|
|
joinBody := new(bytes.Buffer)
|
|
writer := multipart.NewWriter(joinBody)
|
|
part, err := writer.CreateFormFile(channelparticipation.FormDataConfigBlockKey, "join-config.block")
|
|
require.NoError(t, err)
|
|
part.Write(blockBytes)
|
|
err = writer.Close()
|
|
require.NoError(t, err)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, channelparticipation.URLBaseV1Channels, joinBody)
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
|
return req
|
|
}
|
|
|
|
func validBlockBytes(channelID string) []byte {
|
|
blockBytes := protoutil.MarshalOrPanic(blockWithGroups(map[string]*common.ConfigGroup{
|
|
"Application": {},
|
|
}, channelID))
|
|
return blockBytes
|
|
}
|
|
|
|
func sysChanBlockBytes(channelID string) []byte {
|
|
blockBytes := protoutil.MarshalOrPanic(blockWithGroups(map[string]*common.ConfigGroup{
|
|
"Consortiums": {},
|
|
}, channelID))
|
|
return blockBytes
|
|
}
|