diff --git a/pkg/controller/command/presentproof/command.go b/pkg/controller/command/presentproof/command.go index 3e531805e..9f3e002be 100644 --- a/pkg/controller/command/presentproof/command.go +++ b/pkg/controller/command/presentproof/command.go @@ -173,12 +173,15 @@ func (c *Command) SendRequestPresentation(rw io.Writer, req io.Reader) command.E return command.NewValidationError(InvalidRequestErrorCode, errors.New(errEmptyRequestPresentation)) } - if _, err := c.client.SendRequestPresentation(args.RequestPresentation, args.MyDID, args.TheirDID); err != nil { + piid, err := c.client.SendRequestPresentation(args.RequestPresentation, args.MyDID, args.TheirDID) + if err != nil { logutil.LogError(logger, commandName, sendRequestPresentation, err.Error()) return command.NewExecuteError(SendRequestPresentationErrorCode, err) } - command.WriteNillableResponse(rw, &SendRequestPresentationResponse{}, logger) + command.WriteNillableResponse(rw, &SendRequestPresentationResponse{ + PIID: piid, + }, logger) logutil.LogDebug(logger, commandName, sendRequestPresentation, successString) @@ -210,14 +213,15 @@ func (c *Command) SendProposePresentation(rw io.Writer, req io.Reader) command.E return command.NewValidationError(InvalidRequestErrorCode, errors.New(errEmptyProposePresentation)) } - // TODO correlate outbound request-presentation & propose-presentation to their responses - // https://github.com/hyperledger/aries-framework-go/issues/1945 - if _, err := c.client.SendProposePresentation(args.ProposePresentation, args.MyDID, args.TheirDID); err != nil { + piid, err := c.client.SendProposePresentation(args.ProposePresentation, args.MyDID, args.TheirDID) + if err != nil { logutil.LogError(logger, commandName, sendProposePresentation, err.Error()) return command.NewExecuteError(SendProposePresentationErrorCode, err) } - command.WriteNillableResponse(rw, &SendProposePresentationResponse{}, logger) + command.WriteNillableResponse(rw, &SendProposePresentationResponse{ + PIID: piid, + }, logger) logutil.LogDebug(logger, commandName, sendProposePresentation, successString) diff --git a/pkg/controller/command/presentproof/models.go b/pkg/controller/command/presentproof/models.go index 7b8d08b60..38b14729a 100644 --- a/pkg/controller/command/presentproof/models.go +++ b/pkg/controller/command/presentproof/models.go @@ -154,7 +154,10 @@ type SendProposePresentationArgs struct { // // Represents a SendProposePresentation response message // -type SendProposePresentationResponse struct{} +type SendProposePresentationResponse struct { + // PIID Protocol instance ID. It can be used as a correlation ID + PIID string `json:"piid"` +} // SendRequestPresentationArgs model // @@ -173,4 +176,7 @@ type SendRequestPresentationArgs struct { // // Represents a SendRequestPresentation response message // -type SendRequestPresentationResponse struct{} +type SendRequestPresentationResponse struct { + // PIID Protocol instance ID. It can be used as a correlation ID + PIID string `json:"piid"` +} diff --git a/pkg/controller/rest/presentproof/models.go b/pkg/controller/rest/presentproof/models.go index 5fe27ba6d..ec5be9f28 100644 --- a/pkg/controller/rest/presentproof/models.go +++ b/pkg/controller/rest/presentproof/models.go @@ -54,7 +54,10 @@ type presentProofSendRequestPresentationRequest struct { // nolint: unused,deadc // swagger:response presentProofSendRequestPresentationResponse type presentProofSendRequestPresentationResponse struct { // nolint: unused,deadcode // in: body - Body struct{} + Body struct { + // PIID Protocol instance ID. It can be used as a correlation ID + PIID string `json:"piid"` + } } // presentProofSendProposePresentationRequest model @@ -84,7 +87,10 @@ type presentProofSendProposePresentationRequest struct { // nolint: unused,deadc // swagger:response presentProofSendProposePresentationResponse type presentProofSendProposePresentationResponse struct { // nolint: unused,deadcode // in: body - Body struct{} + Body struct { + // PIID Protocol instance ID. It can be used as a correlation ID + PIID string `json:"piid"` + } } // presentProofAcceptRequestPresentationRequest model diff --git a/pkg/didcomm/protocol/presentproof/properties.go b/pkg/didcomm/protocol/presentproof/properties.go new file mode 100644 index 000000000..d0abc6352 --- /dev/null +++ b/pkg/didcomm/protocol/presentproof/properties.go @@ -0,0 +1,74 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package presentproof + +import "errors" + +const ( + myDIDPropKey = "myDID" + theirDIDPropKey = "theirDID" + piidPropKey = "piid" + errorPropKey = "error" +) + +type eventProps struct { + myDID string + theirDID string + piid string + err error +} + +func newEventProps(md *metaData) *eventProps { + return &eventProps{ + myDID: md.MyDID, + theirDID: md.TheirDID, + piid: md.PIID, + err: md.err, + } +} + +func (e *eventProps) MyDID() string { + return e.myDID +} + +func (e *eventProps) TheirDID() string { + return e.theirDID +} + +func (e *eventProps) PIID() string { + return e.piid +} + +func (e eventProps) Err() error { + if errors.As(e.err, &customError{}) { + return nil + } + + return e.err +} + +// All implements EventProperties interface +func (e eventProps) All() map[string]interface{} { + all := map[string]interface{}{} + if e.myDID != "" { + all[myDIDPropKey] = e.myDID + } + + if e.theirDID != "" { + all[theirDIDPropKey] = e.theirDID + } + + if e.piid != "" { + all[piidPropKey] = e.piid + } + + if e.Err() != nil { + all[errorPropKey] = e.Err() + } + + return all +} diff --git a/pkg/didcomm/protocol/presentproof/properties_test.go b/pkg/didcomm/protocol/presentproof/properties_test.go new file mode 100644 index 000000000..3bd4462b6 --- /dev/null +++ b/pkg/didcomm/protocol/presentproof/properties_test.go @@ -0,0 +1,41 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package presentproof + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestEventProps_All(t *testing.T) { + md := &metaData{} + md.MyDID = "MyDID" + md.TheirDID = "TheirDID" + md.PIID = "PIID" + md.err = errors.New("error") + + props := newEventProps(md) + + require.Equal(t, md.MyDID, props.MyDID()) + require.Equal(t, md.TheirDID, props.TheirDID()) + require.Equal(t, md.PIID, props.PIID()) + require.Equal(t, md.err, props.Err()) + require.Equal(t, 4, len(props.All())) + + md.err = customError{errors.New("error")} + md.MyDID = "" + + props = newEventProps(md) + + require.Equal(t, md.MyDID, props.MyDID()) + require.Equal(t, md.TheirDID, props.TheirDID()) + require.Equal(t, md.PIID, props.PIID()) + require.Equal(t, nil, props.Err()) + require.Equal(t, 2, len(props.All())) +} diff --git a/pkg/didcomm/protocol/presentproof/service.go b/pkg/didcomm/protocol/presentproof/service.go index 81ccc4fe0..2b3d30b1f 100644 --- a/pkg/didcomm/protocol/presentproof/service.go +++ b/pkg/didcomm/protocol/presentproof/service.go @@ -568,27 +568,14 @@ func (s *Service) newDIDCommActionMsg(md *metaData) service.DIDCommAction { md.err = customError{error: cErr} s.processCallback(md) }, - Properties: &eventProps{ - myDID: md.MyDID, - theirDID: md.TheirDID, - }, + Properties: newEventProps(md), } } func (s *Service) execute(next state, md *metaData) (state, stateAction, error) { - s.sendMsgEvents(&service.StateMsg{ - ProtocolName: Name, - Type: service.PreState, - Msg: md.msgClone, - StateID: next.Name(), - }) + s.sendMsgEvents(md, next.Name(), service.PreState) - defer s.sendMsgEvents(&service.StateMsg{ - ProtocolName: Name, - Type: service.PostState, - Msg: md.msgClone, - StateID: next.Name(), - }) + defer s.sendMsgEvents(md, next.Name(), service.PostState) if err := s.middleware.Handle(md); err != nil { return nil, nil, fmt.Errorf("middleware: %w", err) @@ -598,10 +585,16 @@ func (s *Service) execute(next state, md *metaData) (state, stateAction, error) } // sendMsgEvents triggers the message events. -func (s *Service) sendMsgEvents(msg *service.StateMsg) { +func (s *Service) sendMsgEvents(md *metaData, stateID string, stateType service.StateMsgType) { // trigger the message events for _, handler := range s.MsgEvents() { - handler <- *msg + handler <- service.StateMsg{ + ProtocolName: Name, + Type: stateType, + Msg: md.msgClone, + StateID: stateID, + Properties: newEventProps(md), + } } } @@ -620,24 +613,3 @@ func (s *Service) Accept(msgType string) bool { return false } - -type eventProps struct { - myDID string - theirDID string -} - -func (e *eventProps) MyDID() string { - return e.myDID -} - -func (e *eventProps) TheirDID() string { - return e.theirDID -} - -// All implements EventProperties interface -func (e *eventProps) All() map[string]interface{} { - return map[string]interface{}{ - "myDID": e.MyDID(), - "theirDID": e.TheirDID(), - } -} diff --git a/test/bdd/go.mod b/test/bdd/go.mod index bed8fe412..769fa79ed 100644 --- a/test/bdd/go.mod +++ b/test/bdd/go.mod @@ -24,6 +24,7 @@ require ( github.com/piprate/json-gold v0.3.0 github.com/sirupsen/logrus v1.4.2 // indirect github.com/trustbloc/sidetree-core-go v0.1.3 + golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect google.golang.org/genproto v0.0.0-20200211111953-2dc5924e3898 // indirect google.golang.org/grpc v1.27.1 // indirect diff --git a/test/bdd/pkg/didexchange/didexchange_controller_steps.go b/test/bdd/pkg/didexchange/didexchange_controller_steps.go index 4a39157eb..277998e78 100644 --- a/test/bdd/pkg/didexchange/didexchange_controller_steps.go +++ b/test/bdd/pkg/didexchange/didexchange_controller_steps.go @@ -7,20 +7,15 @@ SPDX-License-Identifier: Apache-2.0 package didexchange import ( - "bytes" - rqCtx "context" "crypto/ed25519" "encoding/json" "fmt" - "io" - "io/ioutil" "net/http" "strings" "time" "github.com/btcsuite/btcutil/base58" "github.com/cucumber/godog" - "nhooyr.io/websocket/wsjson" "github.com/hyperledger/aries-framework-go/pkg/client/didexchange" "github.com/hyperledger/aries-framework-go/pkg/common/log" @@ -29,6 +24,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/doc/jose" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/sidetree" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) const ( @@ -43,7 +39,6 @@ const ( connectionsByID = connOperationID + "/{id}" createKeySetPath = legacyKMSOperationID + "/keyset" timeoutWaitForDID = 10 * time.Second - timeoutPullTopics = 5 * time.Second sideTreeURL = "${SIDETREE_URL}" ) @@ -111,39 +106,16 @@ func (a *ControllerSteps) ConnectionIDs() map[string]string { } func (a *ControllerSteps) pullEventsFromWebSocket(agentID, state string) (string, error) { - conn, ok := a.bddContext.GetWebSocketConn(agentID) - if !ok { - return "", fmt.Errorf("unable to get websocket conn for agent [%s]", agentID) - } - - ctx, cancel := rqCtx.WithTimeout(rqCtx.Background(), timeoutPullTopics) - defer cancel() - - var incoming struct { - ID string `json:"id"` - Topic string `json:"topic"` - Message struct { - StateID string - Properties map[string]string - Type string - } `json:"message"` + msg, err := util.PullEventsFromWebSocket(a.bddContext, agentID, + util.FilterTopic("didexchange_states"), + util.FilterStateID(state), + util.FilterType("post_state"), + ) + if err != nil { + return "", fmt.Errorf("pull events from WebSocket: %w", err) } - for { - err := wsjson.Read(ctx, conn, &incoming) - if err != nil { - return "", fmt.Errorf("failed to get topics for agent '%s' : %w", agentID, err) - } - - if incoming.Topic == "didexchange_states" && incoming.Message.Type == "post_state" { - if strings.EqualFold(state, incoming.Message.StateID) { - logger.Debugf("Able to find webhook topic with expected state[%s] for agent[%s] and connection[%s]", - incoming.Message.StateID, agentID, incoming.Message.Properties["connectionID"]) - - return incoming.Message.Properties["connectionID"], nil - } - } - } + return msg.Message.Properties["connectionID"].(string), nil } func (a *ControllerSteps) createInvitation(inviterAgentID, label string) error { @@ -185,7 +157,7 @@ func (a *ControllerSteps) performCreateInvitation(inviterAgentID, label string, var result didexcmd.CreateInvitationResponse - err := sendHTTP(http.MethodPost, path, nil, &result) + err := util.SendHTTP(http.MethodPost, path, nil, &result) if err != nil { logger.Errorf("Failed to create invitation, cause : %s", err) return err @@ -232,7 +204,7 @@ func (a *ControllerSteps) performCreateImplicitInvitation(inviteeAgentID, invite var result didexcmd.ImplicitInvitationResponse - err := sendHTTP(http.MethodPost, path, nil, &result) + err := util.SendHTTP(http.MethodPost, path, nil, &result) if err != nil { logger.Errorf("Failed to create implicit invitation, cause : %s", err) return err @@ -292,7 +264,7 @@ func (a *ControllerSteps) receiveInvitation(inviteeAgentID, inviterAgentID strin // call controller var result didexcmd.ReceiveInvitationResponse - err = sendHTTP(http.MethodPost, destination+receiveInvtiationPath, message, &result) + err = util.SendHTTP(http.MethodPost, destination+receiveInvtiationPath, message, &result) if err != nil { logger.Errorf("Failed to perform receive invitation, cause : %s", err) return err @@ -376,7 +348,7 @@ func (a *ControllerSteps) performApprove(agentID string, useDID bool, connection path := controllerURL + fmt.Sprintf(operationPath, connectionID, publicDID) - err := sendHTTP(http.MethodPost, path, nil, &response) + err := util.SendHTTP(http.MethodPost, path, nil, &response) if err != nil { logger.Errorf("Failed to perform approve request, cause : %s", err) return fmt.Errorf("failed to perform approve request : %w", err) @@ -435,7 +407,8 @@ func (a *ControllerSteps) validateConnection(agentID, stateValue string) error { // call controller var response didexcmd.QueryConnectionResponse - err := sendHTTP(http.MethodGet, destination+strings.Replace(connectionsByID, "{id}", connectionID, 1), nil, &response) + err := util.SendHTTP(http.MethodGet, + destination+strings.Replace(connectionsByID, "{id}", connectionID, 1), nil, &response) if err != nil { logger.Errorf("Failed to perform receive invitation, cause : %s", err) return err @@ -463,7 +436,7 @@ func (a *ControllerSteps) verifyConnectionList(agentID, queryState, verifyID str // call controller var response didexcmd.QueryConnectionsResponse - err := sendHTTP(http.MethodGet, destination+connOperationID+"?state="+queryState, nil, &response) + err := util.SendHTTP(http.MethodGet, destination+connOperationID+"?state="+queryState, nil, &response) if err != nil { logger.Errorf("Failed to perform receive invitation, cause : %s", err) return err @@ -509,7 +482,7 @@ func (a *ControllerSteps) createPublicDID(agentID, didMethod string) error { var result cmdkms.CreateKeySetResponse - err = sendHTTP(http.MethodPost, path, reqBytes, &result) + err = util.SendHTTP(http.MethodPost, path, reqBytes, &result) if err != nil { return err } @@ -560,7 +533,7 @@ func (a *ControllerSteps) waitForPublicDID(id string) error { break } - err := sendHTTP(http.MethodGet, endpointURL+"/identifiers/"+id, nil, nil) + err := util.SendHTTP(http.MethodGet, endpointURL+"/identifiers/"+id, nil, nil) if err != nil { logger.Warnf("Failed to resolve public DID, due to error [%s] will retry", err) time.Sleep(retryDelay) @@ -612,47 +585,3 @@ func (a *ControllerSteps) performDIDExchange(inviter, invitee string) error { return nil } - -func sendHTTP(method, destination string, message []byte, result interface{}) error { - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - logger.Debugf("Got response from '%s' [method: %s], response payload: %s", destination, method, string(data)) - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if result == nil { - return nil - } - - return json.Unmarshal(data, result) -} - -func closeResponse(c io.Closer) { - err := c.Close() - if err != nil { - logger.Errorf("Failed to close response body : %s", err) - } -} diff --git a/test/bdd/pkg/introduce/introduce_controller_steps.go b/test/bdd/pkg/introduce/introduce_controller_steps.go index 9e45e8d21..a683a26fe 100644 --- a/test/bdd/pkg/introduce/introduce_controller_steps.go +++ b/test/bdd/pkg/introduce/introduce_controller_steps.go @@ -7,12 +7,9 @@ SPDX-License-Identifier: Apache-2.0 package introduce import ( - "bytes" "encoding/json" "errors" "fmt" - "io" - "io/ioutil" "net/http" "strings" "time" @@ -20,16 +17,14 @@ import ( "github.com/cucumber/godog" client "github.com/hyperledger/aries-framework-go/pkg/client/introduce" - "github.com/hyperledger/aries-framework-go/pkg/common/log" "github.com/hyperledger/aries-framework-go/pkg/controller/command/introduce" outofbandcmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/outofband" protocol "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/introduce" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" bddoutofband "github.com/hyperledger/aries-framework-go/test/bdd/pkg/outofband" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) -var logger = log.New("aries-framework/bdd/introduce") - var errNoActions = errors.New("no actions") const ( @@ -123,7 +118,7 @@ func (s *ControllerSteps) handleRequest(agentID, introducee string) error { url := controllerURL + strings.Replace(acceptRequestWithRecipients, "{piid}", action.PIID, 1) - return sendHTTP(http.MethodPost, url, payload, nil) + return util.SendHTTP(http.MethodPost, url, payload, nil) } func (s *ControllerSteps) checkAndContinueWithInvitation(agentID, introduceeID string) error { @@ -162,7 +157,7 @@ func (s *ControllerSteps) checkAndContinueWithInvitation(agentID, introduceeID s url := controllerURL + strings.Replace(acceptProposalWithOOBRequest, "{piid}", action.PIID, 1) - return sendHTTP(http.MethodPost, url, payload, nil) + return util.SendHTTP(http.MethodPost, url, payload, nil) } func (s *ControllerSteps) sendProposal(introducer, introducee1, introducee2 string) error { @@ -198,7 +193,7 @@ func (s *ControllerSteps) sendProposal(introducer, introducee1, introducee2 stri return fmt.Errorf("marshal send proposal: %w", err) } - return sendHTTP(http.MethodPost, controllerURL+sendProposal, req, nil) + return util.SendHTTP(http.MethodPost, controllerURL+sendProposal, req, nil) } func (s *ControllerSteps) handleRequestWithInvitation(agentID string) error { @@ -236,7 +231,7 @@ func (s *ControllerSteps) handleRequestWithInvitation(agentID string) error { url := controllerURL + strings.Replace(acceptRequestWithPublicOOBRequest, "{piid}", action.PIID, 1) - return sendHTTP(http.MethodPost, url, msg, nil) + return util.SendHTTP(http.MethodPost, url, msg, nil) } func (s *ControllerSteps) establishConnection(inviters, invitee string) error { @@ -270,7 +265,7 @@ func (s *ControllerSteps) sendRequest(introducee1, introducer, introducee2 strin return fmt.Errorf("marshal send proposal: %w", err) } - return sendHTTP(http.MethodPost, controllerURL+sendRequest, req, nil) + return util.SendHTTP(http.MethodPost, controllerURL+sendRequest, req, nil) } func (s *ControllerSteps) sendProposalWithInvitation(introducer, introducee1, introducee2 string) error { @@ -302,7 +297,7 @@ func (s *ControllerSteps) sendProposalWithInvitation(introducer, introducee1, in return fmt.Errorf("marshal send proposal: %w", err) } - return sendHTTP(http.MethodPost, controllerURL+sendProposalWithOOBRequest, req, nil) + return util.SendHTTP(http.MethodPost, controllerURL+sendProposalWithOOBRequest, req, nil) } func (s *ControllerSteps) getAction(retries int, agentID string) (*client.Action, error) { @@ -317,7 +312,7 @@ func (s *ControllerSteps) getAction(retries int, agentID string) (*client.Action res := introduce.ActionsResponse{} - err := sendHTTP(http.MethodGet, fmt.Sprintf(controllerURL+actions), nil, &res) + err := util.SendHTTP(http.MethodGet, fmt.Sprintf(controllerURL+actions), nil, &res) if err != nil { return nil, fmt.Errorf("failed to get actions: %w", err) } @@ -365,7 +360,7 @@ func (s *ControllerSteps) checkAndContinue(agentID, introduceeID string) error { url := controllerURL + strings.Replace(acceptProposal, "{piid}", action.PIID, 1) - err = sendHTTP(http.MethodPost, url, nil, nil) + err = util.SendHTTP(http.MethodPost, url, nil, nil) if err != nil { return fmt.Errorf("accept proposal: %w", err) } @@ -381,7 +376,7 @@ func (s *ControllerSteps) tryOutofbandContinue(agent1 string) error { res := outofbandcmd.ActionsResponse{} - err := sendHTTP(http.MethodGet, fmt.Sprintf(controllerURL+outofbandActions), nil, &res) + err := util.SendHTTP(http.MethodGet, fmt.Sprintf(controllerURL+outofbandActions), nil, &res) if err != nil { return fmt.Errorf("failed to get actions: %w", err) } @@ -392,7 +387,7 @@ func (s *ControllerSteps) tryOutofbandContinue(agent1 string) error { url := strings.Replace(controllerURL+actionContinue+"?label="+agent1, "{piid}", res.Actions[0].PIID, 1) - return sendHTTP(http.MethodPost, url, nil, &res) + return util.SendHTTP(http.MethodPost, url, nil, &res) } func (s *ControllerSteps) outofbandContinue(retries int, agent string, agents ...string) error { @@ -423,46 +418,3 @@ func (s *ControllerSteps) connectionEstablished(agent1, agent2 string) error { return s.outofband.CheckConnection(agent1, agent2) } - -func sendHTTP(method, destination string, message []byte, result interface{}) error { - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - logger.Debugf("Got response from '%s' [method: %s], response payload: %s", destination, method, string(data)) - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if result == nil { - return nil - } - - return json.Unmarshal(data, result) -} - -func closeResponse(c io.Closer) { - if err := c.Close(); err != nil { - logger.Errorf("failed to close response body: %s", err) - } -} diff --git a/test/bdd/pkg/issuecredential/issuecredential_controller_steps.go b/test/bdd/pkg/issuecredential/issuecredential_controller_steps.go index 63325bda3..c71b6fddb 100644 --- a/test/bdd/pkg/issuecredential/issuecredential_controller_steps.go +++ b/test/bdd/pkg/issuecredential/issuecredential_controller_steps.go @@ -7,25 +7,22 @@ SPDX-License-Identifier: Apache-2.0 package issuecredential import ( - "bytes" "encoding/json" "errors" "fmt" - "io" - "io/ioutil" "net/http" "time" "github.com/cucumber/godog" client "github.com/hyperledger/aries-framework-go/pkg/client/issuecredential" - "github.com/hyperledger/aries-framework-go/pkg/common/log" didexcmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/didexchange" issuecredentialcmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/issuecredential" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" protocol "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/issuecredential" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" didexsteps "github.com/hyperledger/aries-framework-go/test/bdd/pkg/didexchange" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) const ( @@ -41,8 +38,6 @@ const ( acceptCredential = operationID + "/%s/accept-credential" ) -var logger = log.New("aries-framework/issuecredential-tests") - // ControllerSteps is steps for issuecredential with controller type ControllerSteps struct { bddContext *context.BDDContext @@ -97,7 +92,7 @@ func (s *ControllerSteps) establishConnection(holder, issuer string) error { connectionsURL := fmt.Sprintf("%s/connections/%s", controllerURL, connID) - err = sendHTTP(http.MethodGet, connectionsURL, nil, &response) + err = util.SendHTTP(http.MethodGet, connectionsURL, nil, &response) if err != nil { return fmt.Errorf("failed to query connections: %w", err) } @@ -250,7 +245,7 @@ func (s *ControllerSteps) validateCredential(holder, credential string) error { var result interface{} - err := sendHTTP(http.MethodGet, fmt.Sprintf("%s/verifiable/credential/name/%s", url, credential), nil, &result) + err := util.SendHTTP(http.MethodGet, fmt.Sprintf("%s/verifiable/credential/name/%s", url, credential), nil, &result) if err != nil { time.Sleep(retryDelay) continue @@ -279,7 +274,7 @@ func actionPIID(endpoint string) (string, error) { Actions []protocol.Action `json:"actions"` } - err := sendHTTP(http.MethodGet, endpoint+actions, nil, &result) + err := util.SendHTTP(http.MethodGet, endpoint+actions, nil, &result) if err != nil { return "", fmt.Errorf("failed to get action PIID: %w", err) } @@ -309,56 +304,5 @@ func postToURL(url string, payload interface{}) error { return err } - var result interface{} - - err = sendHTTP(http.MethodPost, url, body, &result) - if err != nil { - return fmt.Errorf("failed to send HTTP: %w", err) - } - - return nil -} - -func sendHTTP(method, destination string, message []byte, result interface{}) error { - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - logger.Debugf("Got response from '%s' [method: %s], response payload: %s", destination, method, string(data)) - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if result == nil { - return nil - } - - return json.Unmarshal(data, result) -} - -func closeResponse(c io.Closer) { - err := c.Close() - if err != nil { - logger.Errorf("failed to close response body: %s", err) - } + return util.SendHTTP(http.MethodPost, url, body, nil) } diff --git a/test/bdd/pkg/mediator/mediator_controller_steps.go b/test/bdd/pkg/mediator/mediator_controller_steps.go index c26e07b0b..7c59ce115 100644 --- a/test/bdd/pkg/mediator/mediator_controller_steps.go +++ b/test/bdd/pkg/mediator/mediator_controller_steps.go @@ -7,11 +7,8 @@ SPDX-License-Identifier: Apache-2.0 package mediator import ( - "bytes" "encoding/json" "fmt" - "io" - "io/ioutil" "net/http" "strings" @@ -20,6 +17,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/common/log" "github.com/hyperledger/aries-framework-go/pkg/controller/command/mediator" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) var logger = log.New("aries-framework/tests/messaging") @@ -47,7 +45,7 @@ func (d *RESTSteps) RegisterRoute(agentID, varName string) error { return fmt.Errorf(" unable to find controller URL registered for agent [%s]", agentID) } - err := sendHTTP(http.MethodPost, destination+"/mediator/register", registerRouteReq{ConnectionID: connectionID}, nil) + err := postToURL(destination+"/mediator/register", registerRouteReq{ConnectionID: connectionID}) if err != nil { return fmt.Errorf("router registration : %w", err) } @@ -55,6 +53,15 @@ func (d *RESTSteps) RegisterRoute(agentID, varName string) error { return nil } +func postToURL(url string, payload interface{}) error { + body, err := json.Marshal(payload) + if err != nil { + return err + } + + return util.SendHTTP(http.MethodPost, url, body, nil) +} + // UnregisterRoute unregisters the router. func (d *RESTSteps) UnregisterRoute(agentID string) error { destination, ok := d.bddContext.GetControllerURL(agentID) @@ -62,7 +69,7 @@ func (d *RESTSteps) UnregisterRoute(agentID string) error { return fmt.Errorf(" unable to find controller URL registered for agent [%s]", agentID) } - err := sendHTTP(http.MethodDelete, destination+"/mediator/unregister", nil, nil) + err := util.SendHTTP(http.MethodDelete, destination+"/mediator/unregister", nil, nil) if err != nil { // ignore error if router is not registered (code=5003) if strings.Contains(err.Error(), "\"code\":5003") { @@ -86,7 +93,7 @@ func (d *RESTSteps) VerifyConnection(agentID, varName string) error { resp := &mediator.RegisterRoute{} - err := sendHTTP(http.MethodGet, destination+"/mediator/connection", nil, resp) + err := util.SendHTTP(http.MethodGet, destination+"/mediator/connection", nil, resp) if err != nil { return fmt.Errorf("fetch route connection : %w", err) } @@ -110,52 +117,3 @@ func (d *RESTSteps) RegisterSteps(s *godog.Suite) { s.Step(`^"([^"]*)" unregisters the router$`, d.UnregisterRoute) s.Step(`^"([^"]*)" verifies that the router connection is set to "([^"]*)"$`, d.VerifyConnection) } - -func sendHTTP(method, destination string, reqMsg, respMsg interface{}) error { - message, err := json.Marshal(reqMsg) - if err != nil { - return fmt.Errorf("failed to prepare params : %w", err) - } - - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - logger.Debugf("Got response from '%s' [method: %s], response payload: %s", destination, method, string(data)) - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if respMsg == nil { - return nil - } - - return json.Unmarshal(data, respMsg) -} - -func closeResponse(c io.Closer) { - err := c.Close() - if err != nil { - logger.Errorf("Failed to close response body : %s", err) - } -} diff --git a/test/bdd/pkg/messaging/messaging_controller_steps.go b/test/bdd/pkg/messaging/messaging_controller_steps.go index ad1c5c268..a998720bc 100644 --- a/test/bdd/pkg/messaging/messaging_controller_steps.go +++ b/test/bdd/pkg/messaging/messaging_controller_steps.go @@ -10,12 +10,9 @@ package messaging import ( - "bytes" rqCtx "context" "encoding/json" "fmt" - "io" - "io/ioutil" "net/http" "strings" "time" @@ -29,6 +26,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" "github.com/hyperledger/aries-framework-go/pkg/didcomm/messaging/service/basic" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) const ( @@ -90,7 +88,7 @@ func (d *ControllerSteps) registerMsgService(agentID, name, msgType, purpose str logger.Debugf("Registering message service for agent[%s], params : %s", params) // call controller - err = sendHTTP(http.MethodPost, destination+registerMsgService, params, nil) + err = postToURL(destination+registerMsgService, params) if err != nil { return fmt.Errorf("failed to register message service[%s] : %w", name, err) } @@ -131,7 +129,7 @@ func (d *ControllerSteps) unregisterAllMsgServices(agentID, destination string) logger.Debugf("Unregistering message service[%s] for agent[%s]: %w", svcName, agentID) // call controller - err := sendHTTP(http.MethodPost, destination+unregisterMsgService, params, nil) + err := postToURL(destination+unregisterMsgService, params) if err != nil { return fmt.Errorf("failed to unregister message service[%s] for agent[%s]: %w", svcName, agentID, err) } @@ -143,7 +141,7 @@ func (d *ControllerSteps) unregisterAllMsgServices(agentID, destination string) func (d *ControllerSteps) getServicesList(url string) ([]string, error) { result := messaging.RegisteredServicesResponse{} // call controller - err := sendHTTP(http.MethodGet, url, nil, &result) + err := util.SendHTTP(http.MethodGet, url, nil, &result) if err != nil { return nil, fmt.Errorf("failed to get service list, cause : %w", err) } @@ -177,7 +175,7 @@ func (d *ControllerSteps) sendMessage(fromAgentID, toAgentID string, msg interfa } // call controller to send message - err = sendHTTP(http.MethodPost, destination+sendNewMsg, request, nil) + err = postToURL(destination+sendNewMsg, request) if err != nil { return fmt.Errorf("failed to send message : %w", err) } @@ -206,7 +204,7 @@ func (d *ControllerSteps) sendMessageReply(fromAgentID, toAgentID, msgID string, } // call controller to send message - err = sendHTTP(http.MethodPost, destination+sendReplyMsg, request, nil) + err = postToURL(destination+sendReplyMsg, request) if err != nil { return fmt.Errorf("failed to send message : %w", err) } @@ -240,7 +238,7 @@ func (d *ControllerSteps) sendMessageToDID(fromAgentID, toAgentID string, msg in } // call controller to send message - err = sendHTTP(http.MethodPost, destination+sendNewMsg, request, nil) + err = postToURL(destination+sendNewMsg, request) if err != nil { return fmt.Errorf("failed to send message : %w", err) } @@ -257,7 +255,7 @@ func (d *ControllerSteps) findConnection(agentID string) (string, error) { // call controller var response didexchange.QueryConnectionsResponse - err := sendHTTP(http.MethodGet, destination+queryConnections+"?state=completed", nil, &response) + err := util.SendHTTP(http.MethodGet, destination+queryConnections+"?state=completed", nil, &response) if err != nil { return "", fmt.Errorf("failed to query connections : %w", err) } @@ -302,6 +300,15 @@ func (d *ControllerSteps) pullMsgFromWebhookSocket(agentID, topic string) (*serv } } +func postToURL(url string, payload interface{}) error { + body, err := json.Marshal(payload) + if err != nil { + return err + } + + return util.SendHTTP(http.MethodPost, url, body, nil) +} + func (d *ControllerSteps) pullMsgFromWebhookURL(agentID, topic string) (*service.DIDCommMsgMap, error) { webhookURL, ok := d.bddContext.GetWebhookURL(agentID) if !ok { @@ -316,7 +323,7 @@ func (d *ControllerSteps) pullMsgFromWebhookURL(agentID, topic string) (*service // try to pull recently pushed topics from webhook for i := 0; i < pullTopicsAttemptsBeforeFail; { - err := sendHTTP(http.MethodGet, webhookURL+checkForTopics, nil, &incoming) + err := util.SendHTTP(http.MethodGet, webhookURL+checkForTopics, nil, &incoming) if err != nil { return nil, fmt.Errorf("failed pull topics from webhook, cause : %w", err) } @@ -337,48 +344,6 @@ func (d *ControllerSteps) pullMsgFromWebhookURL(agentID, topic string) (*service return nil, fmt.Errorf("exhausted all [%d] attempts to pull topics from webhook", pullTopicsAttemptsBeforeFail) } -func sendHTTP(method, destination string, param, result interface{}) error { - message, err := json.Marshal(param) - if err != nil { - return fmt.Errorf("failed to prepare params : %w", err) - } - - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - logger.Debugf("Got response from '%s' [method: %s], response payload: %s", destination, method, string(data)) - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if result == nil { - return nil - } - - return json.Unmarshal(data, result) -} - func (d *ControllerSteps) registerBasicMsgService(agentID, name string) error { return d.registerMsgService(agentID, name, basic.MessageRequestType, "") } @@ -525,13 +490,6 @@ func (d *ControllerSteps) receiveBasicMessage(agentID, expectedMsg, topic, from return nil } -func closeResponse(c io.Closer) { - err := c.Close() - if err != nil { - logger.Errorf("Failed to close response body : %s", err) - } -} - // SetContext is called before every scenario is run with a fresh new context func (d *ControllerSteps) SetContext(ctx *context.BDDContext) { d.bddContext = ctx diff --git a/test/bdd/pkg/outofband/outofband_controller_steps.go b/test/bdd/pkg/outofband/outofband_controller_steps.go index e4749312b..19ed45ca7 100644 --- a/test/bdd/pkg/outofband/outofband_controller_steps.go +++ b/test/bdd/pkg/outofband/outofband_controller_steps.go @@ -7,12 +7,9 @@ SPDX-License-Identifier: Apache-2.0 package outofband import ( - "bytes" "encoding/json" "errors" "fmt" - "io" - "io/ioutil" "net/http" "strings" @@ -21,16 +18,14 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/client/didexchange" "github.com/hyperledger/aries-framework-go/pkg/client/outofband" - "github.com/hyperledger/aries-framework-go/pkg/common/log" didexcmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/didexchange" outofbandcmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/outofband" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" didexsteps "github.com/hyperledger/aries-framework-go/test/bdd/pkg/didexchange" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) -var logger = log.New("aries-framework/bdd/outofband") - const ( connections = "/connections" createRequest = "/outofband/create-request" @@ -114,7 +109,7 @@ func (s *ControllerSteps) acceptInvitationAndConnect(receiverID, senderID string res := outofbandcmd.AcceptInvitationResponse{} - err = sendHTTP(http.MethodPost, controllerURL+acceptInvitation, payload, &res) + err = util.SendHTTP(http.MethodPost, controllerURL+acceptInvitation, payload, &res) if err != nil { return fmt.Errorf("accept invitation: %w", err) } @@ -174,7 +169,7 @@ func (s *ControllerSteps) newInvitation(agentID string) (*outofband.Invitation, res := outofbandcmd.CreateInvitationResponse{} - return res.Invitation, sendHTTP(http.MethodPost, controllerURL+createInvitation, req, &res) + return res.Invitation, util.SendHTTP(http.MethodPost, controllerURL+createInvitation, req, &res) } // GetConnection returns a connection between agents @@ -186,7 +181,7 @@ func (s *ControllerSteps) GetConnection(receiverID, senderID string) (*didexchan var response didexcmd.QueryConnectionsResponse - err := sendHTTP(http.MethodGet, controllerURL+connections, nil, &response) + err := util.SendHTTP(http.MethodGet, controllerURL+connections, nil, &response) if err != nil { return nil, fmt.Errorf("failed to query connections: %w", err) } @@ -225,7 +220,7 @@ func (s *ControllerSteps) acceptRequestAndConnect(receiverID, senderID string) e res := outofbandcmd.AcceptRequestResponse{} - err = sendHTTP(http.MethodPost, controllerURL+acceptRequest, payload, &res) + err = util.SendHTTP(http.MethodPost, controllerURL+acceptRequest, payload, &res) if err != nil { return fmt.Errorf("accept request: %w", err) } @@ -284,7 +279,7 @@ func (s *ControllerSteps) NewRequest(agentID string) (*outofband.Request, error) res := outofbandcmd.CreateRequestResponse{} - return res.Request, sendHTTP(http.MethodPost, controllerURL+createRequest, req, &res) + return res.Request, util.SendHTTP(http.MethodPost, controllerURL+createRequest, req, &res) } // ConnectAll connects all agents to each other. @@ -324,46 +319,3 @@ func (s *ControllerSteps) ConnectAll(agents string) error { return nil } - -func sendHTTP(method, destination string, message []byte, result interface{}) error { - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - logger.Debugf("Got response from '%s' [method: %s], response payload: %s", destination, method, string(data)) - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if result == nil { - return nil - } - - return json.Unmarshal(data, result) -} - -func closeResponse(c io.Closer) { - if err := c.Close(); err != nil { - logger.Errorf("failed to close response body: %s", err) - } -} diff --git a/test/bdd/pkg/presentproof/presentproof_controller_steps.go b/test/bdd/pkg/presentproof/presentproof_controller_steps.go index c6e3aa2da..66b36936d 100644 --- a/test/bdd/pkg/presentproof/presentproof_controller_steps.go +++ b/test/bdd/pkg/presentproof/presentproof_controller_steps.go @@ -7,31 +7,25 @@ SPDX-License-Identifier: Apache-2.0 package presentproof import ( - "bytes" "encoding/json" "errors" "fmt" - "io" - "io/ioutil" "net/http" - "time" "github.com/cucumber/godog" "github.com/hyperledger/aries-framework-go/pkg/client/presentproof" - "github.com/hyperledger/aries-framework-go/pkg/common/log" didexcmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/didexchange" presentproofcmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/presentproof" "github.com/hyperledger/aries-framework-go/pkg/controller/command/verifiable" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" - protocol "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" didexsteps "github.com/hyperledger/aries-framework-go/test/bdd/pkg/didexchange" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) const ( operationID = "/presentproof" - actions = operationID + "/actions" sendRequestPresentation = operationID + "/send-request-presentation" sendProposalPresentation = operationID + "/send-propose-presentation" acceptProposePresentation = operationID + "/%s/accept-propose-presentation" @@ -41,8 +35,6 @@ const ( verifiablePresentations = "/verifiable/presentations" ) -var logger = log.New("aries-framework/presentproof-tests") - // ControllerSteps supports steps for Present Proof controller type ControllerSteps struct { bddContext *context.BDDContext @@ -132,7 +124,7 @@ func (s *ControllerSteps) negotiateRequestPresentation(agent string) error { return fmt.Errorf("unable to find controller URL registered for agent [%s]", agent) } - piid, err := actionPIID(url) + piid, err := s.actionPIID(agent) if err != nil { return err } @@ -148,7 +140,7 @@ func (s *ControllerSteps) acceptProposePresentation(verifier string) error { return fmt.Errorf("unable to find controller URL registered for agent [%s]", verifier) } - piid, err := actionPIID(url) + piid, err := s.actionPIID(verifier) if err != nil { return err } @@ -164,7 +156,7 @@ func (s *ControllerSteps) acceptRequestPresentation(prover string) error { return fmt.Errorf("unable to find controller URL registered for agent [%s]", prover) } - piid, err := actionPIID(url) + piid, err := s.actionPIID(prover) if err != nil { return err } @@ -186,7 +178,7 @@ func (s *ControllerSteps) acceptPresentation(verifier, name string) error { return fmt.Errorf("unable to find controller URL registered for agent [%s]", verifier) } - piid, err := actionPIID(url) + piid, err := s.actionPIID(verifier) if err != nil { return err } @@ -196,30 +188,38 @@ func (s *ControllerSteps) acceptPresentation(verifier, name string) error { }) } +func (s *ControllerSteps) actionPIID(agentID string) (string, error) { + msg, err := util.PullEventsFromWebSocket(s.bddContext, agentID, util.FilterTopic("present-proof_actions")) + if err != nil { + return "", fmt.Errorf("pull events from WebSocket: %w", err) + } + + return msg.Message.Properties["piid"].(string), nil +} + func (s *ControllerSteps) checkPresentation(verifier, name string) error { url, ok := s.bddContext.GetControllerURL(verifier) if !ok { return fmt.Errorf("unable to find controller URL registered for agent [%s]", verifier) } - const ( - maxRetry = 10 - delay = time.Second + _, err := util.PullEventsFromWebSocket(s.bddContext, verifier, + util.FilterTopic("present-proof_states"), + util.FilterStateID("done"), ) + if err != nil { + return fmt.Errorf("pull events from WebSocket: %w", err) + } - for i := 0; i < maxRetry; i++ { - var result verifiable.RecordResult - if err := sendHTTP(http.MethodGet, url+verifiablePresentations, nil, &result); err != nil { - return err - } + var result verifiable.RecordResult + if err := util.SendHTTP(http.MethodGet, url+verifiablePresentations, nil, &result); err != nil { + return err + } - for _, val := range result.Result { - if val.Name == name { - return nil - } + for _, val := range result.Result { + if val.Name == name { + return nil } - - time.Sleep(delay) } return errors.New("presentation not found") @@ -238,7 +238,7 @@ func (s *ControllerSteps) agentDID(ds *didexsteps.ControllerSteps, agent string) var response didexcmd.QueryConnectionResponse - err := sendHTTP(http.MethodGet, fmt.Sprintf("%s/connections/%s", controllerURL, connectionID), nil, &response) + err := util.SendHTTP(http.MethodGet, fmt.Sprintf("%s/connections/%s", controllerURL, connectionID), nil, &response) if err != nil { return "", fmt.Errorf("failed to query connections: %w", err) } @@ -246,96 +246,11 @@ func (s *ControllerSteps) agentDID(ds *didexsteps.ControllerSteps, agent string) return response.Result.MyDID, nil } -func actionPIID(endpoint string) (string, error) { - const ( - timeoutWait = 10 * time.Second - retryDelay = 500 * time.Millisecond - ) - - start := time.Now() - - for { - if time.Since(start) > timeoutWait { - break - } - - var result struct { - Actions []protocol.Action `json:"actions"` - } - - err := sendHTTP(http.MethodGet, endpoint+actions, nil, &result) - if err != nil { - return "", fmt.Errorf("failed to get action PIID: %w", err) - } - - if len(result.Actions) == 0 { - time.Sleep(retryDelay) - continue - } - - if result.Actions[0].MyDID == "" { - return "", errors.New("myDID is empty") - } - - if result.Actions[0].TheirDID == "" { - return "", errors.New("theirDID is empty") - } - - return result.Actions[0].PIID, nil - } - - return "", fmt.Errorf("unable to get action PIID: timeout") -} - func postToURL(url string, payload interface{}) error { body, err := json.Marshal(payload) if err != nil { return err } - return sendHTTP(http.MethodPost, url, body, nil) -} - -func sendHTTP(method, destination string, message []byte, result interface{}) error { - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - logger.Debugf("Got response from '%s' [method: %s], response payload: %s", destination, method, string(data)) - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if result == nil { - return nil - } - - return json.Unmarshal(data, &result) -} - -func closeResponse(c io.Closer) { - err := c.Close() - if err != nil { - logger.Errorf("failed to close response body: %s", err) - } + return util.SendHTTP(http.MethodPost, url, body, nil) } diff --git a/test/bdd/pkg/sidetree/sidetree.go b/test/bdd/pkg/sidetree/sidetree.go index ecf835984..5f548d0a3 100644 --- a/test/bdd/pkg/sidetree/sidetree.go +++ b/test/bdd/pkg/sidetree/sidetree.go @@ -7,11 +7,8 @@ SPDX-License-Identifier: Apache-2.0 package sidetree import ( - "bytes" "encoding/json" "fmt" - "io" - "io/ioutil" "net/http" "github.com/btcsuite/btcutil/base58" @@ -21,6 +18,7 @@ import ( diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" "github.com/hyperledger/aries-framework-go/pkg/doc/jose" + "github.com/hyperledger/aries-framework-go/test/bdd/pkg/util" ) const docTemplate = `{ @@ -79,7 +77,7 @@ func CreateDID(params *CreateDIDParams) (*diddoc.Doc, error) { var result didResolution - err = sendHTTP(http.MethodPost, params.URL, req, &result) + err = util.SendHTTP(http.MethodPost, params.URL, req, &result) if err != nil { return nil, err } @@ -146,45 +144,3 @@ func getCreateRequest(doc []byte, jwk *jose.JWK) ([]byte, error) { MultihashCode: sha2_256, }) } - -func sendHTTP(method, destination string, message []byte, result interface{}) error { - // create request - req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) - if err != nil { - return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) - } - - // set headers - req.Header.Set("Content-Type", "application/json") - - // send http request - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) - } - - defer closeResponse(resp.Body) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) - } - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ - "and message [%s]", destination, resp.StatusCode, string(data)) - } - - if result == nil { - return nil - } - - return json.Unmarshal(data, result) -} - -func closeResponse(c io.Closer) { - err := c.Close() - if err != nil { - fmt.Printf("Failed to close response body : %s\n", err) - } -} diff --git a/test/bdd/pkg/util/util.go b/test/bdd/pkg/util/util.go new file mode 100644 index 000000000..d0fdbbea1 --- /dev/null +++ b/test/bdd/pkg/util/util.go @@ -0,0 +1,141 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package util + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "time" + + "golang.org/x/net/context" + "nhooyr.io/websocket/wsjson" + + bddcontext "github.com/hyperledger/aries-framework-go/test/bdd/pkg/context" +) + +// SendHTTP sends HTTP request +func SendHTTP(method, destination string, message []byte, result interface{}) error { + // create request + req, err := http.NewRequest(method, destination, bytes.NewBuffer(message)) + if err != nil { + return fmt.Errorf("failed to create new http '%s' request for '%s', cause: %s", method, destination, err) + } + + // set headers + req.Header.Set("Content-Type", "application/json") + + // send http request + resp, err := http.DefaultClient.Do(req) + if err != nil { + return fmt.Errorf("failed to get response from '%s', cause :%s", destination, err) + } + + // nolint: errcheck + defer resp.Body.Close() + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("unable to read response from '%s', cause :%s", destination, err) + } + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("failed to get successful response from '%s', unexpected status code [%d], "+ + "and message [%s]", destination, resp.StatusCode, string(data)) + } + + if result == nil { + return nil + } + + return json.Unmarshal(data, &result) +} + +// PullEventsFromWebSocket returns WebSocket event by given filter +// nolint: gocyclo +func PullEventsFromWebSocket(bdd *bddcontext.BDDContext, agentID string, filters ...Filter) (*Incoming, error) { + const timeoutPullTopics = 5 * time.Second + + conn, ok := bdd.GetWebSocketConn(agentID) + if !ok { + return nil, fmt.Errorf("unable to get websocket conn for agent [%s]", agentID) + } + + filter := &eventFilter{} + + for i := range filters { + filters[i](filter) + } + + ctx, cancel := context.WithTimeout(context.Background(), timeoutPullTopics) + defer cancel() + + for { + var incoming *Incoming + + if err := wsjson.Read(ctx, conn, &incoming); err != nil { + return nil, fmt.Errorf("failed to get topics for agent '%s' : %w", agentID, err) + } + + if filter.Topic != nil && incoming.Topic != *filter.Topic { + continue + } + + if filter.StateID != nil && incoming.Message.StateID != *filter.StateID { + continue + } + + if filter.Type != nil && incoming.Message.Type != *filter.Type { + continue + } + + return incoming, nil + } +} + +type eventFilter struct { + Topic *string + StateID *string + Type *string +} + +// Filter is an option for the PullEventsFromWebSocket function +type Filter func(*eventFilter) + +// FilterTopic filters WebSocket events by topic +func FilterTopic(val string) Filter { + return func(filter *eventFilter) { + filter.Topic = &val + } +} + +// FilterStateID filters WebSocket events by stateID +func FilterStateID(val string) Filter { + return func(filter *eventFilter) { + filter.StateID = &val + } +} + +// FilterType filters WebSocket events by type +func FilterType(val string) Filter { + return func(filter *eventFilter) { + filter.Type = &val + } +} + +// Incoming represents WebSocket event message +type Incoming struct { + ID string `json:"id"` + Topic string `json:"topic"` + Message struct { + StateID string + Properties map[string]interface{} + Type string + } `json:"message"` +}