Skip to content

Commit

Permalink
Various Utilities in Support of the Token-SDK (hyperledger-labs#487)
Browse files Browse the repository at this point in the history
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Alexandros Filios <[email protected]>
  • Loading branch information
alexandrosfilios authored Aug 11, 2023
1 parent 34da6a1 commit a925afa
Show file tree
Hide file tree
Showing 63 changed files with 1,657 additions and 287 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.9
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/hyperledger-labs/orion-sdk-go v0.2.5
github.com/hyperledger-labs/orion-server v0.2.5
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
Expand Down
7 changes: 7 additions & 0 deletions integration/fsc/pingpong/cmd/initiator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package main

import (
"github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong"
"github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong/mock"
fscnode "github.com/hyperledger-labs/fabric-smart-client/node"
"github.com/hyperledger-labs/fabric-smart-client/platform/view"
)
Expand All @@ -19,6 +20,12 @@ func main() {
if err := registry.RegisterFactory("init", &pingpong.InitiatorViewFactory{}); err != nil {
return err
}
if err := registry.RegisterFactory("mockInit", &mock.InitiatorViewFactory{}); err != nil {
return err
}
if err := registry.RegisterFactory("stream", &pingpong.StreamerViewFactory{}); err != nil {
return err
}
return nil
})
}
4 changes: 4 additions & 0 deletions integration/fsc/pingpong/cmd/responder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package main

import (
"github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong"
"github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong/mock"
fscnode "github.com/hyperledger-labs/fabric-smart-client/node"
"github.com/hyperledger-labs/fabric-smart-client/platform/view"
)
Expand All @@ -20,6 +21,9 @@ func main() {
if err := registry.RegisterResponder(&pingpong.Responder{}, initiatorID); err != nil {
return err
}
if err := registry.RegisterResponder(&pingpong.Responder{}, &mock.Initiator{}); err != nil {
return err
}
return nil
})
}
2 changes: 1 addition & 1 deletion integration/fsc/pingpong/initiator.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (p *Initiator) Call(context view.Context) (interface{}, error) {
}
m := string(msg.Payload)
if m != "pong" {
return nil, fmt.Errorf("exptectd pong, got %s", m)
return nil, fmt.Errorf("expected pong, got %s", m)
}
case <-time.After(1 * time.Minute):
return nil, errors.New("responder didn't pong in time")
Expand Down
25 changes: 25 additions & 0 deletions integration/fsc/pingpong/mock/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package mock

import (
"encoding/json"

"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/assert"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
)

// InitiatorViewFactory is the factory of Initiator views
type InitiatorViewFactory struct{}

// NewView returns a new instance of the Initiator view
func (i *InitiatorViewFactory) NewView(in []byte) (view.View, error) {
f := &Initiator{Params: &Params{}}
err := json.Unmarshal(in, f.Params)
assert.NoError(err, "failed unmarshalling input")
return f, nil
}
62 changes: 62 additions & 0 deletions integration/fsc/pingpong/mock/initiator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package mock

import (
"fmt"
"time"

view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/assert"
view3 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
"github.com/pkg/errors"
)

type Params struct {
Mock bool
}

type Initiator struct {
*Params
}

func (p *Initiator) Call(ctx view.Context) (interface{}, error) {
// Retrieve responder identity
responder := view2.GetIdentityProvider(ctx).Identity("responder")
var context view.Context
if p.Mock {
c := &view3.MockContext{Ctx: ctx}
c.RespondToAs(ctx.Initiator(), responder, &Responder{})
context = c
} else {
context = ctx
}

// Open a session to the responder
session, err := context.GetSession(context.Initiator(), responder)
assert.NoError(err) // Send a ping

err = session.Send([]byte("ping"))
assert.NoError(err) // Wait for the pong
ch := session.Receive()
select {
case msg := <-ch:
if msg.Status == view.ERROR {
return nil, errors.New(string(msg.Payload))
}
m := string(msg.Payload)
if m != "mock pong" {
return nil, fmt.Errorf("expected mock pong, got %s", m)
}
case <-time.After(1 * time.Minute):
return nil, errors.New("responder didn't pong in time")
}

// Return
return "OK", nil
}
49 changes: 49 additions & 0 deletions integration/fsc/pingpong/mock/responder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package mock

import (
"errors"
"fmt"
"time"

"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/assert"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
)

type Responder struct{}

func (p *Responder) Call(context view.Context) (interface{}, error) {
// Retrieve the session opened by the initiator
session := context.Session()

// Read the message from the initiator
ch := session.Receive()
var payload []byte
select {
case msg := <-ch:
payload = msg.Payload
case <-time.After(5 * time.Second):
return nil, errors.New("time out reached")
}
// Respond with a pong if a ping is received, an error otherwise
m := string(payload)
switch {
case m != "ping":
// reply with an error
err := session.SendError([]byte(fmt.Sprintf("expected ping, got %s", m)))
assert.NoError(err)
return nil, fmt.Errorf("expected ping, got %s", m)
default:
// reply with pong
err := session.Send([]byte("mock pong"))
assert.NoError(err)
}

// Return
return "OK", nil
}
145 changes: 142 additions & 3 deletions integration/fsc/pingpong/pingpong_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ package pingpong_test

import (
"bytes"
"strings"
"time"

"github.com/hyperledger-labs/fabric-smart-client/integration"
"github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong"
"github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong/mock"
"github.com/hyperledger-labs/fabric-smart-client/integration/nwo/client"
"github.com/hyperledger-labs/fabric-smart-client/integration/nwo/common"
"github.com/hyperledger-labs/fabric-smart-client/pkg/api"
Expand All @@ -32,7 +34,9 @@ var _ = Describe("EndToEnd", func() {
AfterEach(func() {
// Stop the ii
initiator.Stop()
responder.Stop()
if responder != nil {
responder.Stop()
}
time.Sleep(5 * time.Second)
})

Expand All @@ -56,7 +60,7 @@ var _ = Describe("EndToEnd", func() {

time.Sleep(3 * time.Second)

webClientConfig, err := client.NewWebClientConfigFromFSC("./testdata/fsc/nodes/webclient")
webClientConfig, err := client.NewWebClientConfigFromFSC("./testdata/fsc/nodes/initiator")
Expect(err).NotTo(HaveOccurred())
initiatorWebClient, err := web.NewClient(webClientConfig)
Expect(err).NotTo(HaveOccurred())
Expand All @@ -67,7 +71,7 @@ var _ = Describe("EndToEnd", func() {
Expect(err).NotTo(HaveOccurred())
Expect(version).To(BeEquivalentTo("{\"CommitSHA\":\"development build\",\"Version\":\"latest\"}"))

webClientConfig.TLSCert = ""
webClientConfig.TLSCertPath = ""
initiatorWebClient, err = web.NewClient(webClientConfig)
Expect(err).NotTo(HaveOccurred())
_, err = initiatorWebClient.CallView("init", bytes.NewBuffer([]byte("hi")).Bytes())
Expand All @@ -78,6 +82,33 @@ var _ = Describe("EndToEnd", func() {
Expect(version).To(BeEquivalentTo("{\"CommitSHA\":\"development build\",\"Version\":\"latest\"}"))
})

It("successful pingpong based on WebSocket", func() {
// Init and Start fsc nodes
initiator = node.NewFromConfPath("./testdata/fsc/nodes/initiator")
Expect(initiator).NotTo(BeNil())

err := initiator.Start()
Expect(err).NotTo(HaveOccurred())

// Register views and view factories
err = initiator.RegisterFactory("stream", &pingpong.StreamerViewFactory{})
Expect(err).NotTo(HaveOccurred())

time.Sleep(3 * time.Second)

initiatorWebClient := newWebClient("./testdata/fsc/nodes/initiator")
stream, err := initiatorWebClient.StreamCallView("stream", nil)
Expect(err).NotTo(HaveOccurred())
var s string
Expect(stream.Recv(&s)).NotTo(HaveOccurred())
Expect(s).To(BeEquivalentTo("hello"))
Expect(stream.Send("ciao")).NotTo(HaveOccurred())

res, err := stream.Result()
Expect(err).NotTo(HaveOccurred())
Expect(common.JSONUnmarshalString(res)).To(BeEquivalentTo("OK"))
})

It("successful pingpong", func() {
// Init and Start fsc nodes
initiator = node.NewFromConfPath("./testdata/fsc/nodes/initiator")
Expand Down Expand Up @@ -148,6 +179,71 @@ var _ = Describe("EndToEnd", func() {
Expect(common.JSONUnmarshalString(res)).To(BeEquivalentTo("OK"))
})

It("load artifact & successful pingpong with stream", func() {
var err error
// Create the integration ii
ii, err = integration.Load(0, "./testdata", true, pingpong.Topology()...)
Expect(err).NotTo(HaveOccurred())
// Start the integration ii
ii.Start()
time.Sleep(3 * time.Second)
// Get a client for the fsc node labelled initiator
initiator := ii.Client("initiator")
// Initiate a view and check the output
channel, err := initiator.StreamCallView("init", nil)
Expect(err).NotTo(HaveOccurred())

res, err := channel.Result()
Expect(err).NotTo(HaveOccurred())
Expect(common.JSONUnmarshalString(res)).To(BeEquivalentTo("OK"))
})

It("load artifact & successful stream", func() {
var err error
// Create the integration ii
ii, err = integration.Load(0, "./testdata", true, pingpong.Topology()...)
Expect(err).NotTo(HaveOccurred())
// Start the integration ii
ii.Start()
time.Sleep(10 * time.Second)
// Get a client for the fsc node labelled initiator
initiator := ii.Client("initiator")
// Initiate a view and check the output
channel, err := initiator.StreamCallView("stream", nil)
Expect(err).NotTo(HaveOccurred())
var s string
Expect(channel.Recv(&s)).NotTo(HaveOccurred())
Expect(s).To(BeEquivalentTo("hello"))
Expect(channel.Send("ciao")).NotTo(HaveOccurred())

res, err := channel.Result()
Expect(err).NotTo(HaveOccurred())
Expect(common.JSONUnmarshalString(res)).To(BeEquivalentTo("OK"))
})

It("load artifact & successful stream with websocket", func() {
var err error
// Create the integration ii
ii, err = integration.Load(0, "./testdata", true, pingpong.Topology()...)
Expect(err).NotTo(HaveOccurred())
// Start the integration ii
ii.Start()
time.Sleep(10 * time.Second)
// Get a client for the fsc node labelled initiator
initiator := ii.WebClient("initiator")
// Initiate a view and check the output
channel, err := initiator.StreamCallView("stream", nil)
Expect(err).NotTo(HaveOccurred())
var s string
Expect(channel.Recv(&s)).NotTo(HaveOccurred())
Expect(s).To(BeEquivalentTo("hello"))
Expect(channel.Send("ciao")).NotTo(HaveOccurred())

res, err := channel.Result()
Expect(err).NotTo(HaveOccurred())
Expect(common.JSONUnmarshalString(res)).To(BeEquivalentTo("OK"))
})

It("load artifact & init clients & successful pingpong", func() {
var err error
// Create the integration ii
Expand All @@ -170,4 +266,47 @@ var _ = Describe("EndToEnd", func() {
})
})

Describe("Network-based Mock Ping pong", func() {
var (
ii *integration.Infrastructure
)

AfterEach(func() {
// Stop the ii
ii.DeleteOnStop = true
ii.Stop()
})

It("generate artifacts & successful mock pingpong", func() {
var err error
// Create the integration ii
ii, err = integration.Generate(StartPortWithGeneration(), true, pingpong.Topology()...)
Expect(err).NotTo(HaveOccurred())
// Start the integration ii
ii.Start()
time.Sleep(3 * time.Second)

// Get a client for the fsc node labelled initiator
initiator := ii.Client("initiator")

// Init with mock=false, a failure must happen
_, err = initiator.CallView("mockInit", common.JSONMarshall(&mock.Params{Mock: false}))
Expect(err).To(HaveOccurred())
Expect(strings.Contains(err.Error(), "expected mock pong, got pong")).To(BeTrue())

// Init with mock=true, a success must happen
res, err := initiator.CallView("mockInit", common.JSONMarshall(&mock.Params{Mock: true}))
Expect(err).NotTo(HaveOccurred())
Expect(common.JSONUnmarshalString(res)).To(BeEquivalentTo("OK"))
})

})
})

func newWebClient(confDir string) *web.Client {
c, err := client.NewWebClientConfigFromFSC(confDir)
Expect(err).NotTo(HaveOccurred())
initiator, err := web.NewClient(c)
Expect(err).NotTo(HaveOccurred())
return initiator
}
Loading

0 comments on commit a925afa

Please sign in to comment.