From dd5d425e536affc8eca4e0d87518ef3ea52d61ca Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Sun, 23 Nov 2025 10:13:39 +0100 Subject: [PATCH 1/4] ability to run a view with a different context Signed-off-by: Angelo De Caro --- integration/fsc/pingpong/mock/initiator.go | 4 +- platform/view/services/view/child.go | 141 +++ platform/view/services/view/context.go | 169 +-- platform/view/services/view/manager.go | 25 +- platform/view/services/view/mock/context.go | 885 ++++++++++++++ .../view/services/view/mock/parent_context.go | 1023 +++++++++++++++++ .../view/services/view/{ => mock}/runner.go | 55 +- platform/view/services/view/mock/view.go | 117 ++ platform/view/services/view/view.go | 117 +- platform/view/services/view/view_test.go | 119 ++ platform/view/services/view/wrapper.go | 117 +- platform/view/view/context.go | 10 + 12 files changed, 2491 insertions(+), 291 deletions(-) create mode 100644 platform/view/services/view/child.go create mode 100644 platform/view/services/view/mock/context.go create mode 100644 platform/view/services/view/mock/parent_context.go rename platform/view/services/view/{ => mock}/runner.go (54%) create mode 100644 platform/view/services/view/mock/view.go create mode 100644 platform/view/services/view/view_test.go diff --git a/integration/fsc/pingpong/mock/initiator.go b/integration/fsc/pingpong/mock/initiator.go index d9c8d99cb..5ccffc04e 100644 --- a/integration/fsc/pingpong/mock/initiator.go +++ b/integration/fsc/pingpong/mock/initiator.go @@ -12,7 +12,7 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/assert" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/id" - view3 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view" + view3 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view/mock" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" ) @@ -31,7 +31,7 @@ func (p *Initiator) Call(ctx view.Context) (interface{}, error) { responder := identityProvider.Identity("responder") var context view.Context if p.Mock { - c := &view3.MockContext{Ctx: ctx} + c := &view3.DelegatedContext{Ctx: ctx} c.RespondToAs(ctx.Initiator(), responder, &Responder{}) context = c } else { diff --git a/platform/view/services/view/child.go b/platform/view/services/view/child.go new file mode 100644 index 000000000..213ae87c8 --- /dev/null +++ b/platform/view/services/view/child.go @@ -0,0 +1,141 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package view + +import ( + "context" + + "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" + "go.opentelemetry.io/otel/trace" +) + +//go:generate counterfeiter -o mock/parent_context.go -fake-name ParentContext . ParentContext +type ParentContext interface { + DisposableContext + Cleanup() + PutSession(caller view.View, party view.Identity, session view.Session) error +} + +type ChildContext struct { + Parent ParentContext + + session view.Session + initiator view.View + errorCallbackFuncs []func() +} + +func NewChildContextFromParent(parentContext ParentContext) *ChildContext { + return NewChildContext(parentContext, nil, nil, nil) +} + +func NewChildContextFromParentAndSession(parentContext ParentContext, session view.Session) *ChildContext { + return NewChildContext(parentContext, session, nil, nil) +} + +func NewChildContextFromParentAndInitiator(parentContext ParentContext, initiator view.View) *ChildContext { + return NewChildContext(parentContext, nil, initiator, nil) +} + +func NewChildContext(parentContext ParentContext, session view.Session, initiator view.View, errorCallbackFuncs ...func()) *ChildContext { + return &ChildContext{Parent: parentContext, session: session, initiator: initiator, errorCallbackFuncs: errorCallbackFuncs} +} + +func (w *ChildContext) StartSpanFrom(c context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + return w.Parent.StartSpanFrom(c, name, opts...) +} + +func (w *ChildContext) GetService(v interface{}) (interface{}, error) { + return w.Parent.GetService(v) +} + +func (w *ChildContext) PutService(v interface{}) error { + mutableContext, ok := w.Parent.(view.MutableContext) + if ok { + return mutableContext.PutService(v) + } + return nil +} + +func (w *ChildContext) ID() string { + return w.Parent.ID() +} + +func (w *ChildContext) Me() view.Identity { + return w.Parent.Me() +} + +func (w *ChildContext) IsMe(id view.Identity) bool { + return w.Parent.IsMe(id) +} + +func (w *ChildContext) GetSession(caller view.View, party view.Identity, boundToViews ...view.View) (view.Session, error) { + return w.Parent.GetSession(caller, party, boundToViews...) +} + +func (w *ChildContext) GetSessionByID(id string, party view.Identity) (view.Session, error) { + return w.Parent.GetSessionByID(id, party) +} + +func (w *ChildContext) Context() context.Context { + return w.Parent.Context() +} + +func (w *ChildContext) Session() view.Session { + if w.session == nil { + return w.Parent.Session() + } + return w.session +} + +func (w *ChildContext) ResetSessions() error { + mutableContext, ok := w.Parent.(view.MutableContext) + if ok { + return mutableContext.ResetSessions() + } + return nil +} + +func (w *ChildContext) Initiator() view.View { + if w.initiator == nil { + return w.Parent.Initiator() + } + return w.initiator +} + +func (w *ChildContext) OnError(f func()) { + w.errorCallbackFuncs = append(w.errorCallbackFuncs, f) +} + +func (w *ChildContext) RunView(v view.View, opts ...view.RunViewOption) (res interface{}, err error) { + return RunViewNow(w, v, opts...) +} + +func (w *ChildContext) Dispose() { + if w.Parent != nil { + w.Parent.Dispose() + } +} + +func (w *ChildContext) PutSession(caller view.View, party view.Identity, session view.Session) error { + return w.Parent.PutSession(caller, party, session) +} + +func (w *ChildContext) Cleanup() { + logger.Debugf("cleaning up child context [%s][%d]", w.ID(), len(w.errorCallbackFuncs)) + for _, callbackFunc := range w.errorCallbackFuncs { + w.safeInvoke(callbackFunc) + } +} + +func (w *ChildContext) safeInvoke(f func()) { + defer func() { + if r := recover(); r != nil { + logger.Debugf("function [%s] panicked [%s]", f, r) + } + }() + f() +} diff --git a/platform/view/services/view/context.go b/platform/view/services/view/context.go index d4daa707a..29bbf0816 100644 --- a/platform/view/services/view/context.go +++ b/platform/view/services/view/context.go @@ -17,37 +17,33 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/endpoint" - "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/tracing" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) -type localContext interface { - disposableContext - cleanup() - PutSession(caller view.View, party view.Identity, session view.Session) error -} - +// LocalIdentityChecker models the dependency to the view-sdk's sig service type LocalIdentityChecker interface { IsMe(ctx context.Context, id view.Identity) bool } +// EndpointService models the dependency to the view-sdk's endpoint service +// //go:generate counterfeiter -o mock/resolver.go -fake-name EndpointService . EndpointService - type EndpointService interface { GetIdentity(endpoint string, pkID []byte) (view.Identity, error) Resolver(ctx context.Context, party view.Identity) (*endpoint.Resolver, []byte, error) } +// IdentityProvider models the dependency to the view-sdk's identity provider +// //go:generate counterfeiter -o mock/identity_provider.go -fake-name IdentityProvider . IdentityProvider - type IdentityProvider interface { Identity(string) view.Identity DefaultIdentity() view.Identity } -type ctx struct { +// Context implements the view.Context interface +type Context struct { context context.Context sp services.Provider localSP *ServiceProvider @@ -78,7 +74,7 @@ func NewContextForInitiator( initiator view.View, tracer trace.Tracer, localIdentityChecker LocalIdentityChecker, -) (*ctx, error) { +) (*Context, error) { if context == nil { return nil, errors.Errorf("a context should not be nil [%s]", string(debug.Stack())) } @@ -118,11 +114,11 @@ func NewContext( caller view.Identity, tracer trace.Tracer, localIdentityChecker LocalIdentityChecker, -) (*ctx, error) { +) (*Context, error) { if context == nil { return nil, errors.Errorf("a context should not be nil [%s]", string(debug.Stack())) } - ctx := &ctx{ + ctx := &Context{ context: context, id: contextID, resolver: resolver, @@ -146,46 +142,46 @@ func NewContext( return ctx, nil } -func (c *ctx) StartSpan(name string, opts ...trace.SpanStartOption) trace.Span { +func (c *Context) StartSpan(name string, opts ...trace.SpanStartOption) trace.Span { newCtx, span := c.StartSpanFrom(c.context, name, opts...) c.context = newCtx return span } -func (c *ctx) StartSpanFrom(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { +func (c *Context) StartSpanFrom(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return c.tracer.Start(ctx, name, opts...) } -func (c *ctx) ID() string { +func (c *Context) ID() string { return c.id } -func (c *ctx) Initiator() view.View { +func (c *Context) Initiator() view.View { return c.initiator } -func (c *ctx) RunView(v view.View, opts ...view.RunViewOption) (res interface{}, err error) { - return runViewOn(v, opts, c) +func (c *Context) RunView(v view.View, opts ...view.RunViewOption) (res interface{}, err error) { + return RunViewNow(c, v, opts...) } -func (c *ctx) Me() view.Identity { +func (c *Context) Me() view.Identity { return c.me } // Identity returns the identity matching the passed argument -func (c *ctx) Identity(ref string) (view.Identity, error) { +func (c *Context) Identity(ref string) (view.Identity, error) { return c.resolver.GetIdentity(ref, nil) } -func (c *ctx) IsMe(id view.Identity) bool { +func (c *Context) IsMe(id view.Identity) bool { return c.localIdentityChecker.IsMe(c.context, id) } -func (c *ctx) Caller() view.Identity { +func (c *Context) Caller() view.Identity { return c.caller } -func (c *ctx) GetSession(caller view.View, party view.Identity, boundToViews ...view.View) (view.Session, error) { +func (c *Context) GetSession(caller view.View, party view.Identity, boundToViews ...view.View) (view.Session, error) { viewId := getViewIdentifier(caller) // TODO: we need a mechanism to close all the sessions opened in this ctx, // when the ctx goes out of scope @@ -214,7 +210,7 @@ func (c *ctx) GetSession(caller view.View, party view.Identity, boundToViews ... return c.createSession(caller, targetIdentity, boundToViews...) } -func (c *ctx) GetSessionByID(id string, party view.Identity) (view.Session, error) { +func (c *Context) GetSessionByID(id string, party view.Identity) (view.Session, error) { c.sessions.Lock() defer c.sessions.Unlock() @@ -234,7 +230,7 @@ func (c *ctx) GetSessionByID(id string, party view.Identity) (view.Session, erro return s, nil } -func (c *ctx) Session() view.Session { +func (c *Context) Session() view.Session { if c.session == nil { logger.DebugfContext(c.context, "[%s] No default current Session", c.me) return nil @@ -243,7 +239,7 @@ func (c *ctx) Session() view.Session { return c.session } -func (c *ctx) ResetSessions() error { +func (c *Context) ResetSessions() error { c.sessions.Lock() defer c.sessions.Unlock() c.sessions.Reset() @@ -251,11 +247,11 @@ func (c *ctx) ResetSessions() error { return nil } -func (c *ctx) PutService(service interface{}) error { +func (c *Context) PutService(service interface{}) error { return c.localSP.RegisterService(service) } -func (c *ctx) GetService(v interface{}) (interface{}, error) { +func (c *Context) GetService(v interface{}) (interface{}, error) { // first search locally then globally s, err := c.localSP.GetService(v) if err == nil { @@ -264,15 +260,15 @@ func (c *ctx) GetService(v interface{}) (interface{}, error) { return c.sp.GetService(v) } -func (c *ctx) OnError(callback func()) { +func (c *Context) OnError(callback func()) { c.errorCallbackFuncs = append(c.errorCallbackFuncs, callback) } -func (c *ctx) Context() context.Context { +func (c *Context) Context() context.Context { return c.context } -func (c *ctx) Dispose() { +func (c *Context) Dispose() { logger.DebugfContext(c.context, "Dispose sessions") // dispose all sessions c.sessions.Lock() @@ -291,7 +287,7 @@ func (c *ctx) Dispose() { c.sessions.Reset() } -func (c *ctx) newSession(view view.View, contextID string, party view.Identity) (view.Session, error) { +func (c *Context) newSession(view view.View, contextID string, party view.Identity) (view.Session, error) { resolver, pkid, err := c.resolver.Resolver(c.context, party) if err != nil { return nil, err @@ -300,7 +296,7 @@ func (c *ctx) newSession(view view.View, contextID string, party view.Identity) return c.sessionFactory.NewSession(GetIdentifier(view), contextID, resolver.GetAddress(endpoint.P2PPort), pkid) } -func (c *ctx) newSessionByID(sessionID, contextID string, party view.Identity) (view.Session, error) { +func (c *Context) newSessionByID(sessionID, contextID string, party view.Identity) (view.Session, error) { resolver, pkid, err := c.resolver.Resolver(c.context, party) if err != nil { return nil, err @@ -314,14 +310,14 @@ func (c *ctx) newSessionByID(sessionID, contextID string, party view.Identity) ( return c.sessionFactory.NewSessionWithID(sessionID, contextID, ep, pkid, nil, nil) } -func (c *ctx) cleanup() { +func (c *Context) Cleanup() { logger.DebugfContext(c.context, "cleaning up context [%s][%d]", c.ID(), len(c.errorCallbackFuncs)) for _, callbackFunc := range c.errorCallbackFuncs { c.safeInvoke(callbackFunc) } } -func (c *ctx) safeInvoke(f func()) { +func (c *Context) safeInvoke(f func()) { defer func() { if r := recover(); r != nil { logger.DebugfContext(c.context, "function [%s] panicked [%s]", f, r) @@ -330,7 +326,7 @@ func (c *ctx) safeInvoke(f func()) { f() } -func (c *ctx) resolve(id view.Identity) (view.Identity, error) { +func (c *Context) resolve(id view.Identity) (view.Identity, error) { if id.IsNone() { return nil, errors.New("no id provided") } @@ -341,7 +337,7 @@ func (c *ctx) resolve(id view.Identity) (view.Identity, error) { return resolver.GetId(), nil } -func (c *ctx) createSession(caller view.View, party view.Identity, aliases ...view.View) (view.Session, error) { +func (c *Context) createSession(caller view.View, party view.Identity, aliases ...view.View) (view.Session, error) { logger.DebugfContext(c.context, "create session [%s][%s], [%s:%s]", c.me, c.id, getViewIdentifier(caller), party) s, err := c.newSession(caller, c.id, party) @@ -361,7 +357,7 @@ func (c *ctx) createSession(caller view.View, party view.Identity, aliases ...vi return s, nil } -func (c *ctx) PutSession(caller view.View, party view.Identity, session view.Session) error { +func (c *Context) PutSession(caller view.View, party view.Identity, session view.Session) error { c.sessions.Lock() defer c.sessions.Unlock() @@ -370,99 +366,6 @@ func (c *ctx) PutSession(caller view.View, party view.Identity, session view.Ses return nil } -type tempCtx struct { - localContext - newCtx context.Context -} - -func (c *tempCtx) Context() context.Context { - return c.newCtx -} - -func runViewOn(v view.View, opts []view.RunViewOption, ctx localContext) (res interface{}, err error) { - options, err := view.CompileRunViewOptions(opts...) - if err != nil { - return nil, errors.Wrap(err, "failed compiling options") - } - var initiator view.View - if options.AsInitiator { - initiator = v - } - - logger.DebugfContext(ctx.Context(), "Start view %s", GetName(v)) - newCtx, span := ctx.StartSpanFrom(ctx.Context(), GetName(v), tracing.WithAttributes( - tracing.String(ViewLabel, GetIdentifier(v)), - tracing.String(InitiatorViewLabel, GetIdentifier(initiator)), - ), trace.WithSpanKind(trace.SpanKindInternal)) - defer span.End() - - var cc localContext - if options.SameContext { - cc = wrapContext(ctx, newCtx) - } else { - if options.AsInitiator { - cc = &childContext{ - ParentContext: wrapContext(ctx, newCtx), - initiator: initiator, - } - // register options.Session under initiator - contextSession := ctx.Session() - if contextSession == nil { - return nil, errors.Errorf("cannot convert a non-responder context to an initiator context") - } - if err := cc.PutSession(initiator, contextSession.Info().Caller, contextSession); err != nil { - return nil, errors.Wrapf(err, "failed registering default session as initiated by [%s:%s]", initiator, contextSession.Info().Caller) - } - } else { - cc = &childContext{ - ParentContext: wrapContext(ctx, newCtx), - session: options.Session, - initiator: initiator, - } - } - } - - defer func() { - if r := recover(); r != nil { - cc.cleanup() - res = nil - - logger.Errorf("caught panic while running view with [%v][%s]", r, debug.Stack()) - - switch e := r.(type) { - case error: - err = errors.WithMessage(e, "caught panic") - case string: - err = errors.New(e) - default: - err = errors.Errorf("caught panic [%v]", e) - } - } - }() - - if v == nil && options.Call == nil { - return nil, errors.Errorf("no view passed") - } - if options.Call != nil { - res, err = options.Call(cc) - } else { - res, err = v.Call(cc) - } - span.SetAttributes(attribute.Bool(SuccessLabel, err != nil)) - if err != nil { - cc.cleanup() - return nil, err - } - return res, err -} - -func wrapContext(ctx localContext, newCtx context.Context) localContext { - return &tempCtx{ - localContext: ctx, - newCtx: newCtx, - } -} - func getViewIdentifier(f view.View) string { if f == nil { return "" diff --git a/platform/view/services/view/manager.go b/platform/view/services/view/manager.go index a30271628..5ef5aecd8 100644 --- a/platform/view/services/view/manager.go +++ b/platform/view/services/view/manager.go @@ -30,6 +30,12 @@ const ( var logger = logging.MustGetLogger() +// DisposableContext extends view.Context with additional functions +type DisposableContext interface { + view.Context + Dispose() +} + type Manager struct { serviceProvider services.Provider @@ -42,7 +48,7 @@ type Manager struct { localIdentityChecker LocalIdentityChecker ctx context.Context - contexts map[string]disposableContext + contexts map[string]DisposableContext contextsMu sync.RWMutex } @@ -62,7 +68,7 @@ func NewManager( endpointService: endpointService, identityProvider: identityProvider, - contexts: map[string]disposableContext{}, + contexts: map[string]DisposableContext{}, registry: registry, tracer: tracerProvider.Tracer("calls", tracing.WithMetricsOpts(tracing.MetricsOpts{ @@ -139,7 +145,7 @@ func (cm *Manager) InitiateViewWithIdentity(view view.View, id view.Identity, ct if err != nil { return nil, err } - c := &childContext{ParentContext: viewContext} + c := NewChildContextFromParent(viewContext) cm.contextsMu.Lock() cm.contexts[c.ID()] = c cm.metrics.Contexts.Set(float64(len(cm.contexts))) @@ -187,7 +193,7 @@ func (cm *Manager) InitiateContextFrom(ctx context.Context, view view.View, id v if err != nil { return nil, err } - c := &childContext{ParentContext: viewContext} + c := NewChildContextFromParent(viewContext) cm.contextsMu.Lock() cm.contexts[c.ID()] = c cm.metrics.Contexts.Set(float64(len(cm.contexts))) @@ -322,12 +328,12 @@ func (cm *Manager) newContext(id view.Identity, msg *view.Message) (view.Context } // next we need to unwrap the actual context to store the session - vCtx, ok := viewContext.(*childContext) + vCtx, ok := viewContext.(*ChildContext) if !ok { panic("Not a child!") } - vvCtx, ok := vCtx.ParentContext.(*ctx) + vvCtx, ok := vCtx.Parent.(*Context) if !ok { panic("Not a child!") } @@ -335,10 +341,7 @@ func (cm *Manager) newContext(id view.Identity, msg *view.Message) (view.Context vvCtx.sessions.Put(msg.Caller, caller, backend) // we wrap our context and set our new session as the default session - c := &childContext{ - ParentContext: vCtx, - session: backend, - } + c := NewChildContextFromParentAndSession(vCtx, backend) cm.contexts[contextID] = c cm.metrics.Contexts.Set(float64(len(cm.contexts))) @@ -374,7 +377,7 @@ func (cm *Manager) newContext(id view.Identity, msg *view.Message) (view.Context return nil, false, err } - c := &childContext{ParentContext: newCtx} + c := NewChildContextFromParent(newCtx) cm.contexts[contextID] = c cm.metrics.Contexts.Set(float64(len(cm.contexts))) viewContext = c diff --git a/platform/view/services/view/mock/context.go b/platform/view/services/view/mock/context.go new file mode 100644 index 000000000..71c1e8f90 --- /dev/null +++ b/platform/view/services/view/mock/context.go @@ -0,0 +1,885 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package mock + +import ( + "context" + "sync" + + "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view" + viewa "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" + "go.opentelemetry.io/otel/trace" +) + +type Context struct { + ContextStub func() context.Context + contextMutex sync.RWMutex + contextArgsForCall []struct { + } + contextReturns struct { + result1 context.Context + } + contextReturnsOnCall map[int]struct { + result1 context.Context + } + GetServiceStub func(interface{}) (interface{}, error) + getServiceMutex sync.RWMutex + getServiceArgsForCall []struct { + arg1 interface{} + } + getServiceReturns struct { + result1 interface{} + result2 error + } + getServiceReturnsOnCall map[int]struct { + result1 interface{} + result2 error + } + GetSessionStub func(viewa.View, viewa.Identity, ...viewa.View) (viewa.Session, error) + getSessionMutex sync.RWMutex + getSessionArgsForCall []struct { + arg1 viewa.View + arg2 viewa.Identity + arg3 []viewa.View + } + getSessionReturns struct { + result1 viewa.Session + result2 error + } + getSessionReturnsOnCall map[int]struct { + result1 viewa.Session + result2 error + } + GetSessionByIDStub func(string, viewa.Identity) (viewa.Session, error) + getSessionByIDMutex sync.RWMutex + getSessionByIDArgsForCall []struct { + arg1 string + arg2 viewa.Identity + } + getSessionByIDReturns struct { + result1 viewa.Session + result2 error + } + getSessionByIDReturnsOnCall map[int]struct { + result1 viewa.Session + result2 error + } + IDStub func() string + iDMutex sync.RWMutex + iDArgsForCall []struct { + } + iDReturns struct { + result1 string + } + iDReturnsOnCall map[int]struct { + result1 string + } + InitiatorStub func() viewa.View + initiatorMutex sync.RWMutex + initiatorArgsForCall []struct { + } + initiatorReturns struct { + result1 viewa.View + } + initiatorReturnsOnCall map[int]struct { + result1 viewa.View + } + IsMeStub func(viewa.Identity) bool + isMeMutex sync.RWMutex + isMeArgsForCall []struct { + arg1 viewa.Identity + } + isMeReturns struct { + result1 bool + } + isMeReturnsOnCall map[int]struct { + result1 bool + } + MeStub func() viewa.Identity + meMutex sync.RWMutex + meArgsForCall []struct { + } + meReturns struct { + result1 viewa.Identity + } + meReturnsOnCall map[int]struct { + result1 viewa.Identity + } + OnErrorStub func(func()) + onErrorMutex sync.RWMutex + onErrorArgsForCall []struct { + arg1 func() + } + RunViewStub func(viewa.View, ...viewa.RunViewOption) (interface{}, error) + runViewMutex sync.RWMutex + runViewArgsForCall []struct { + arg1 viewa.View + arg2 []viewa.RunViewOption + } + runViewReturns struct { + result1 interface{} + result2 error + } + runViewReturnsOnCall map[int]struct { + result1 interface{} + result2 error + } + SessionStub func() viewa.Session + sessionMutex sync.RWMutex + sessionArgsForCall []struct { + } + sessionReturns struct { + result1 viewa.Session + } + sessionReturnsOnCall map[int]struct { + result1 viewa.Session + } + StartSpanFromStub func(context.Context, string, ...trace.SpanStartOption) (context.Context, trace.Span) + startSpanFromMutex sync.RWMutex + startSpanFromArgsForCall []struct { + arg1 context.Context + arg2 string + arg3 []trace.SpanStartOption + } + startSpanFromReturns struct { + result1 context.Context + result2 trace.Span + } + startSpanFromReturnsOnCall map[int]struct { + result1 context.Context + result2 trace.Span + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *Context) Context() context.Context { + fake.contextMutex.Lock() + ret, specificReturn := fake.contextReturnsOnCall[len(fake.contextArgsForCall)] + fake.contextArgsForCall = append(fake.contextArgsForCall, struct { + }{}) + stub := fake.ContextStub + fakeReturns := fake.contextReturns + fake.recordInvocation("Context", []interface{}{}) + fake.contextMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *Context) ContextCallCount() int { + fake.contextMutex.RLock() + defer fake.contextMutex.RUnlock() + return len(fake.contextArgsForCall) +} + +func (fake *Context) ContextCalls(stub func() context.Context) { + fake.contextMutex.Lock() + defer fake.contextMutex.Unlock() + fake.ContextStub = stub +} + +func (fake *Context) ContextReturns(result1 context.Context) { + fake.contextMutex.Lock() + defer fake.contextMutex.Unlock() + fake.ContextStub = nil + fake.contextReturns = struct { + result1 context.Context + }{result1} +} + +func (fake *Context) ContextReturnsOnCall(i int, result1 context.Context) { + fake.contextMutex.Lock() + defer fake.contextMutex.Unlock() + fake.ContextStub = nil + if fake.contextReturnsOnCall == nil { + fake.contextReturnsOnCall = make(map[int]struct { + result1 context.Context + }) + } + fake.contextReturnsOnCall[i] = struct { + result1 context.Context + }{result1} +} + +func (fake *Context) GetService(arg1 interface{}) (interface{}, error) { + fake.getServiceMutex.Lock() + ret, specificReturn := fake.getServiceReturnsOnCall[len(fake.getServiceArgsForCall)] + fake.getServiceArgsForCall = append(fake.getServiceArgsForCall, struct { + arg1 interface{} + }{arg1}) + stub := fake.GetServiceStub + fakeReturns := fake.getServiceReturns + fake.recordInvocation("GetService", []interface{}{arg1}) + fake.getServiceMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *Context) GetServiceCallCount() int { + fake.getServiceMutex.RLock() + defer fake.getServiceMutex.RUnlock() + return len(fake.getServiceArgsForCall) +} + +func (fake *Context) GetServiceCalls(stub func(interface{}) (interface{}, error)) { + fake.getServiceMutex.Lock() + defer fake.getServiceMutex.Unlock() + fake.GetServiceStub = stub +} + +func (fake *Context) GetServiceArgsForCall(i int) interface{} { + fake.getServiceMutex.RLock() + defer fake.getServiceMutex.RUnlock() + argsForCall := fake.getServiceArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *Context) GetServiceReturns(result1 interface{}, result2 error) { + fake.getServiceMutex.Lock() + defer fake.getServiceMutex.Unlock() + fake.GetServiceStub = nil + fake.getServiceReturns = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *Context) GetServiceReturnsOnCall(i int, result1 interface{}, result2 error) { + fake.getServiceMutex.Lock() + defer fake.getServiceMutex.Unlock() + fake.GetServiceStub = nil + if fake.getServiceReturnsOnCall == nil { + fake.getServiceReturnsOnCall = make(map[int]struct { + result1 interface{} + result2 error + }) + } + fake.getServiceReturnsOnCall[i] = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *Context) GetSession(arg1 viewa.View, arg2 viewa.Identity, arg3 ...viewa.View) (viewa.Session, error) { + fake.getSessionMutex.Lock() + ret, specificReturn := fake.getSessionReturnsOnCall[len(fake.getSessionArgsForCall)] + fake.getSessionArgsForCall = append(fake.getSessionArgsForCall, struct { + arg1 viewa.View + arg2 viewa.Identity + arg3 []viewa.View + }{arg1, arg2, arg3}) + stub := fake.GetSessionStub + fakeReturns := fake.getSessionReturns + fake.recordInvocation("GetSession", []interface{}{arg1, arg2, arg3}) + fake.getSessionMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3...) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *Context) GetSessionCallCount() int { + fake.getSessionMutex.RLock() + defer fake.getSessionMutex.RUnlock() + return len(fake.getSessionArgsForCall) +} + +func (fake *Context) GetSessionCalls(stub func(viewa.View, viewa.Identity, ...viewa.View) (viewa.Session, error)) { + fake.getSessionMutex.Lock() + defer fake.getSessionMutex.Unlock() + fake.GetSessionStub = stub +} + +func (fake *Context) GetSessionArgsForCall(i int) (viewa.View, viewa.Identity, []viewa.View) { + fake.getSessionMutex.RLock() + defer fake.getSessionMutex.RUnlock() + argsForCall := fake.getSessionArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *Context) GetSessionReturns(result1 viewa.Session, result2 error) { + fake.getSessionMutex.Lock() + defer fake.getSessionMutex.Unlock() + fake.GetSessionStub = nil + fake.getSessionReturns = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *Context) GetSessionReturnsOnCall(i int, result1 viewa.Session, result2 error) { + fake.getSessionMutex.Lock() + defer fake.getSessionMutex.Unlock() + fake.GetSessionStub = nil + if fake.getSessionReturnsOnCall == nil { + fake.getSessionReturnsOnCall = make(map[int]struct { + result1 viewa.Session + result2 error + }) + } + fake.getSessionReturnsOnCall[i] = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *Context) GetSessionByID(arg1 string, arg2 viewa.Identity) (viewa.Session, error) { + fake.getSessionByIDMutex.Lock() + ret, specificReturn := fake.getSessionByIDReturnsOnCall[len(fake.getSessionByIDArgsForCall)] + fake.getSessionByIDArgsForCall = append(fake.getSessionByIDArgsForCall, struct { + arg1 string + arg2 viewa.Identity + }{arg1, arg2}) + stub := fake.GetSessionByIDStub + fakeReturns := fake.getSessionByIDReturns + fake.recordInvocation("GetSessionByID", []interface{}{arg1, arg2}) + fake.getSessionByIDMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *Context) GetSessionByIDCallCount() int { + fake.getSessionByIDMutex.RLock() + defer fake.getSessionByIDMutex.RUnlock() + return len(fake.getSessionByIDArgsForCall) +} + +func (fake *Context) GetSessionByIDCalls(stub func(string, viewa.Identity) (viewa.Session, error)) { + fake.getSessionByIDMutex.Lock() + defer fake.getSessionByIDMutex.Unlock() + fake.GetSessionByIDStub = stub +} + +func (fake *Context) GetSessionByIDArgsForCall(i int) (string, viewa.Identity) { + fake.getSessionByIDMutex.RLock() + defer fake.getSessionByIDMutex.RUnlock() + argsForCall := fake.getSessionByIDArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *Context) GetSessionByIDReturns(result1 viewa.Session, result2 error) { + fake.getSessionByIDMutex.Lock() + defer fake.getSessionByIDMutex.Unlock() + fake.GetSessionByIDStub = nil + fake.getSessionByIDReturns = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *Context) GetSessionByIDReturnsOnCall(i int, result1 viewa.Session, result2 error) { + fake.getSessionByIDMutex.Lock() + defer fake.getSessionByIDMutex.Unlock() + fake.GetSessionByIDStub = nil + if fake.getSessionByIDReturnsOnCall == nil { + fake.getSessionByIDReturnsOnCall = make(map[int]struct { + result1 viewa.Session + result2 error + }) + } + fake.getSessionByIDReturnsOnCall[i] = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *Context) ID() string { + fake.iDMutex.Lock() + ret, specificReturn := fake.iDReturnsOnCall[len(fake.iDArgsForCall)] + fake.iDArgsForCall = append(fake.iDArgsForCall, struct { + }{}) + stub := fake.IDStub + fakeReturns := fake.iDReturns + fake.recordInvocation("ID", []interface{}{}) + fake.iDMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *Context) IDCallCount() int { + fake.iDMutex.RLock() + defer fake.iDMutex.RUnlock() + return len(fake.iDArgsForCall) +} + +func (fake *Context) IDCalls(stub func() string) { + fake.iDMutex.Lock() + defer fake.iDMutex.Unlock() + fake.IDStub = stub +} + +func (fake *Context) IDReturns(result1 string) { + fake.iDMutex.Lock() + defer fake.iDMutex.Unlock() + fake.IDStub = nil + fake.iDReturns = struct { + result1 string + }{result1} +} + +func (fake *Context) IDReturnsOnCall(i int, result1 string) { + fake.iDMutex.Lock() + defer fake.iDMutex.Unlock() + fake.IDStub = nil + if fake.iDReturnsOnCall == nil { + fake.iDReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.iDReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *Context) Initiator() viewa.View { + fake.initiatorMutex.Lock() + ret, specificReturn := fake.initiatorReturnsOnCall[len(fake.initiatorArgsForCall)] + fake.initiatorArgsForCall = append(fake.initiatorArgsForCall, struct { + }{}) + stub := fake.InitiatorStub + fakeReturns := fake.initiatorReturns + fake.recordInvocation("Initiator", []interface{}{}) + fake.initiatorMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *Context) InitiatorCallCount() int { + fake.initiatorMutex.RLock() + defer fake.initiatorMutex.RUnlock() + return len(fake.initiatorArgsForCall) +} + +func (fake *Context) InitiatorCalls(stub func() viewa.View) { + fake.initiatorMutex.Lock() + defer fake.initiatorMutex.Unlock() + fake.InitiatorStub = stub +} + +func (fake *Context) InitiatorReturns(result1 viewa.View) { + fake.initiatorMutex.Lock() + defer fake.initiatorMutex.Unlock() + fake.InitiatorStub = nil + fake.initiatorReturns = struct { + result1 viewa.View + }{result1} +} + +func (fake *Context) InitiatorReturnsOnCall(i int, result1 viewa.View) { + fake.initiatorMutex.Lock() + defer fake.initiatorMutex.Unlock() + fake.InitiatorStub = nil + if fake.initiatorReturnsOnCall == nil { + fake.initiatorReturnsOnCall = make(map[int]struct { + result1 viewa.View + }) + } + fake.initiatorReturnsOnCall[i] = struct { + result1 viewa.View + }{result1} +} + +func (fake *Context) IsMe(arg1 viewa.Identity) bool { + fake.isMeMutex.Lock() + ret, specificReturn := fake.isMeReturnsOnCall[len(fake.isMeArgsForCall)] + fake.isMeArgsForCall = append(fake.isMeArgsForCall, struct { + arg1 viewa.Identity + }{arg1}) + stub := fake.IsMeStub + fakeReturns := fake.isMeReturns + fake.recordInvocation("IsMe", []interface{}{arg1}) + fake.isMeMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *Context) IsMeCallCount() int { + fake.isMeMutex.RLock() + defer fake.isMeMutex.RUnlock() + return len(fake.isMeArgsForCall) +} + +func (fake *Context) IsMeCalls(stub func(viewa.Identity) bool) { + fake.isMeMutex.Lock() + defer fake.isMeMutex.Unlock() + fake.IsMeStub = stub +} + +func (fake *Context) IsMeArgsForCall(i int) viewa.Identity { + fake.isMeMutex.RLock() + defer fake.isMeMutex.RUnlock() + argsForCall := fake.isMeArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *Context) IsMeReturns(result1 bool) { + fake.isMeMutex.Lock() + defer fake.isMeMutex.Unlock() + fake.IsMeStub = nil + fake.isMeReturns = struct { + result1 bool + }{result1} +} + +func (fake *Context) IsMeReturnsOnCall(i int, result1 bool) { + fake.isMeMutex.Lock() + defer fake.isMeMutex.Unlock() + fake.IsMeStub = nil + if fake.isMeReturnsOnCall == nil { + fake.isMeReturnsOnCall = make(map[int]struct { + result1 bool + }) + } + fake.isMeReturnsOnCall[i] = struct { + result1 bool + }{result1} +} + +func (fake *Context) Me() viewa.Identity { + fake.meMutex.Lock() + ret, specificReturn := fake.meReturnsOnCall[len(fake.meArgsForCall)] + fake.meArgsForCall = append(fake.meArgsForCall, struct { + }{}) + stub := fake.MeStub + fakeReturns := fake.meReturns + fake.recordInvocation("Me", []interface{}{}) + fake.meMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *Context) MeCallCount() int { + fake.meMutex.RLock() + defer fake.meMutex.RUnlock() + return len(fake.meArgsForCall) +} + +func (fake *Context) MeCalls(stub func() viewa.Identity) { + fake.meMutex.Lock() + defer fake.meMutex.Unlock() + fake.MeStub = stub +} + +func (fake *Context) MeReturns(result1 viewa.Identity) { + fake.meMutex.Lock() + defer fake.meMutex.Unlock() + fake.MeStub = nil + fake.meReturns = struct { + result1 viewa.Identity + }{result1} +} + +func (fake *Context) MeReturnsOnCall(i int, result1 viewa.Identity) { + fake.meMutex.Lock() + defer fake.meMutex.Unlock() + fake.MeStub = nil + if fake.meReturnsOnCall == nil { + fake.meReturnsOnCall = make(map[int]struct { + result1 viewa.Identity + }) + } + fake.meReturnsOnCall[i] = struct { + result1 viewa.Identity + }{result1} +} + +func (fake *Context) OnError(arg1 func()) { + fake.onErrorMutex.Lock() + fake.onErrorArgsForCall = append(fake.onErrorArgsForCall, struct { + arg1 func() + }{arg1}) + stub := fake.OnErrorStub + fake.recordInvocation("OnError", []interface{}{arg1}) + fake.onErrorMutex.Unlock() + if stub != nil { + fake.OnErrorStub(arg1) + } +} + +func (fake *Context) OnErrorCallCount() int { + fake.onErrorMutex.RLock() + defer fake.onErrorMutex.RUnlock() + return len(fake.onErrorArgsForCall) +} + +func (fake *Context) OnErrorCalls(stub func(func())) { + fake.onErrorMutex.Lock() + defer fake.onErrorMutex.Unlock() + fake.OnErrorStub = stub +} + +func (fake *Context) OnErrorArgsForCall(i int) func() { + fake.onErrorMutex.RLock() + defer fake.onErrorMutex.RUnlock() + argsForCall := fake.onErrorArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *Context) RunView(arg1 viewa.View, arg2 ...viewa.RunViewOption) (interface{}, error) { + fake.runViewMutex.Lock() + ret, specificReturn := fake.runViewReturnsOnCall[len(fake.runViewArgsForCall)] + fake.runViewArgsForCall = append(fake.runViewArgsForCall, struct { + arg1 viewa.View + arg2 []viewa.RunViewOption + }{arg1, arg2}) + stub := fake.RunViewStub + fakeReturns := fake.runViewReturns + fake.recordInvocation("RunView", []interface{}{arg1, arg2}) + fake.runViewMutex.Unlock() + if stub != nil { + return stub(arg1, arg2...) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *Context) RunViewCallCount() int { + fake.runViewMutex.RLock() + defer fake.runViewMutex.RUnlock() + return len(fake.runViewArgsForCall) +} + +func (fake *Context) RunViewCalls(stub func(viewa.View, ...viewa.RunViewOption) (interface{}, error)) { + fake.runViewMutex.Lock() + defer fake.runViewMutex.Unlock() + fake.RunViewStub = stub +} + +func (fake *Context) RunViewArgsForCall(i int) (viewa.View, []viewa.RunViewOption) { + fake.runViewMutex.RLock() + defer fake.runViewMutex.RUnlock() + argsForCall := fake.runViewArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *Context) RunViewReturns(result1 interface{}, result2 error) { + fake.runViewMutex.Lock() + defer fake.runViewMutex.Unlock() + fake.RunViewStub = nil + fake.runViewReturns = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *Context) RunViewReturnsOnCall(i int, result1 interface{}, result2 error) { + fake.runViewMutex.Lock() + defer fake.runViewMutex.Unlock() + fake.RunViewStub = nil + if fake.runViewReturnsOnCall == nil { + fake.runViewReturnsOnCall = make(map[int]struct { + result1 interface{} + result2 error + }) + } + fake.runViewReturnsOnCall[i] = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *Context) Session() viewa.Session { + fake.sessionMutex.Lock() + ret, specificReturn := fake.sessionReturnsOnCall[len(fake.sessionArgsForCall)] + fake.sessionArgsForCall = append(fake.sessionArgsForCall, struct { + }{}) + stub := fake.SessionStub + fakeReturns := fake.sessionReturns + fake.recordInvocation("Session", []interface{}{}) + fake.sessionMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *Context) SessionCallCount() int { + fake.sessionMutex.RLock() + defer fake.sessionMutex.RUnlock() + return len(fake.sessionArgsForCall) +} + +func (fake *Context) SessionCalls(stub func() viewa.Session) { + fake.sessionMutex.Lock() + defer fake.sessionMutex.Unlock() + fake.SessionStub = stub +} + +func (fake *Context) SessionReturns(result1 viewa.Session) { + fake.sessionMutex.Lock() + defer fake.sessionMutex.Unlock() + fake.SessionStub = nil + fake.sessionReturns = struct { + result1 viewa.Session + }{result1} +} + +func (fake *Context) SessionReturnsOnCall(i int, result1 viewa.Session) { + fake.sessionMutex.Lock() + defer fake.sessionMutex.Unlock() + fake.SessionStub = nil + if fake.sessionReturnsOnCall == nil { + fake.sessionReturnsOnCall = make(map[int]struct { + result1 viewa.Session + }) + } + fake.sessionReturnsOnCall[i] = struct { + result1 viewa.Session + }{result1} +} + +func (fake *Context) StartSpanFrom(arg1 context.Context, arg2 string, arg3 ...trace.SpanStartOption) (context.Context, trace.Span) { + fake.startSpanFromMutex.Lock() + ret, specificReturn := fake.startSpanFromReturnsOnCall[len(fake.startSpanFromArgsForCall)] + fake.startSpanFromArgsForCall = append(fake.startSpanFromArgsForCall, struct { + arg1 context.Context + arg2 string + arg3 []trace.SpanStartOption + }{arg1, arg2, arg3}) + stub := fake.StartSpanFromStub + fakeReturns := fake.startSpanFromReturns + fake.recordInvocation("StartSpanFrom", []interface{}{arg1, arg2, arg3}) + fake.startSpanFromMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3...) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *Context) StartSpanFromCallCount() int { + fake.startSpanFromMutex.RLock() + defer fake.startSpanFromMutex.RUnlock() + return len(fake.startSpanFromArgsForCall) +} + +func (fake *Context) StartSpanFromCalls(stub func(context.Context, string, ...trace.SpanStartOption) (context.Context, trace.Span)) { + fake.startSpanFromMutex.Lock() + defer fake.startSpanFromMutex.Unlock() + fake.StartSpanFromStub = stub +} + +func (fake *Context) StartSpanFromArgsForCall(i int) (context.Context, string, []trace.SpanStartOption) { + fake.startSpanFromMutex.RLock() + defer fake.startSpanFromMutex.RUnlock() + argsForCall := fake.startSpanFromArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *Context) StartSpanFromReturns(result1 context.Context, result2 trace.Span) { + fake.startSpanFromMutex.Lock() + defer fake.startSpanFromMutex.Unlock() + fake.StartSpanFromStub = nil + fake.startSpanFromReturns = struct { + result1 context.Context + result2 trace.Span + }{result1, result2} +} + +func (fake *Context) StartSpanFromReturnsOnCall(i int, result1 context.Context, result2 trace.Span) { + fake.startSpanFromMutex.Lock() + defer fake.startSpanFromMutex.Unlock() + fake.StartSpanFromStub = nil + if fake.startSpanFromReturnsOnCall == nil { + fake.startSpanFromReturnsOnCall = make(map[int]struct { + result1 context.Context + result2 trace.Span + }) + } + fake.startSpanFromReturnsOnCall[i] = struct { + result1 context.Context + result2 trace.Span + }{result1, result2} +} + +func (fake *Context) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.contextMutex.RLock() + defer fake.contextMutex.RUnlock() + fake.getServiceMutex.RLock() + defer fake.getServiceMutex.RUnlock() + fake.getSessionMutex.RLock() + defer fake.getSessionMutex.RUnlock() + fake.getSessionByIDMutex.RLock() + defer fake.getSessionByIDMutex.RUnlock() + fake.iDMutex.RLock() + defer fake.iDMutex.RUnlock() + fake.initiatorMutex.RLock() + defer fake.initiatorMutex.RUnlock() + fake.isMeMutex.RLock() + defer fake.isMeMutex.RUnlock() + fake.meMutex.RLock() + defer fake.meMutex.RUnlock() + fake.onErrorMutex.RLock() + defer fake.onErrorMutex.RUnlock() + fake.runViewMutex.RLock() + defer fake.runViewMutex.RUnlock() + fake.sessionMutex.RLock() + defer fake.sessionMutex.RUnlock() + fake.startSpanFromMutex.RLock() + defer fake.startSpanFromMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *Context) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ view.ViewContext = new(Context) diff --git a/platform/view/services/view/mock/parent_context.go b/platform/view/services/view/mock/parent_context.go new file mode 100644 index 000000000..023fee9a7 --- /dev/null +++ b/platform/view/services/view/mock/parent_context.go @@ -0,0 +1,1023 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package mock + +import ( + "context" + "sync" + + "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view" + viewa "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" + "go.opentelemetry.io/otel/trace" +) + +type ParentContext struct { + CleanupStub func() + cleanupMutex sync.RWMutex + cleanupArgsForCall []struct { + } + ContextStub func() context.Context + contextMutex sync.RWMutex + contextArgsForCall []struct { + } + contextReturns struct { + result1 context.Context + } + contextReturnsOnCall map[int]struct { + result1 context.Context + } + DisposeStub func() + disposeMutex sync.RWMutex + disposeArgsForCall []struct { + } + GetServiceStub func(interface{}) (interface{}, error) + getServiceMutex sync.RWMutex + getServiceArgsForCall []struct { + arg1 interface{} + } + getServiceReturns struct { + result1 interface{} + result2 error + } + getServiceReturnsOnCall map[int]struct { + result1 interface{} + result2 error + } + GetSessionStub func(viewa.View, viewa.Identity, ...viewa.View) (viewa.Session, error) + getSessionMutex sync.RWMutex + getSessionArgsForCall []struct { + arg1 viewa.View + arg2 viewa.Identity + arg3 []viewa.View + } + getSessionReturns struct { + result1 viewa.Session + result2 error + } + getSessionReturnsOnCall map[int]struct { + result1 viewa.Session + result2 error + } + GetSessionByIDStub func(string, viewa.Identity) (viewa.Session, error) + getSessionByIDMutex sync.RWMutex + getSessionByIDArgsForCall []struct { + arg1 string + arg2 viewa.Identity + } + getSessionByIDReturns struct { + result1 viewa.Session + result2 error + } + getSessionByIDReturnsOnCall map[int]struct { + result1 viewa.Session + result2 error + } + IDStub func() string + iDMutex sync.RWMutex + iDArgsForCall []struct { + } + iDReturns struct { + result1 string + } + iDReturnsOnCall map[int]struct { + result1 string + } + InitiatorStub func() viewa.View + initiatorMutex sync.RWMutex + initiatorArgsForCall []struct { + } + initiatorReturns struct { + result1 viewa.View + } + initiatorReturnsOnCall map[int]struct { + result1 viewa.View + } + IsMeStub func(viewa.Identity) bool + isMeMutex sync.RWMutex + isMeArgsForCall []struct { + arg1 viewa.Identity + } + isMeReturns struct { + result1 bool + } + isMeReturnsOnCall map[int]struct { + result1 bool + } + MeStub func() viewa.Identity + meMutex sync.RWMutex + meArgsForCall []struct { + } + meReturns struct { + result1 viewa.Identity + } + meReturnsOnCall map[int]struct { + result1 viewa.Identity + } + OnErrorStub func(func()) + onErrorMutex sync.RWMutex + onErrorArgsForCall []struct { + arg1 func() + } + PutSessionStub func(viewa.View, viewa.Identity, viewa.Session) error + putSessionMutex sync.RWMutex + putSessionArgsForCall []struct { + arg1 viewa.View + arg2 viewa.Identity + arg3 viewa.Session + } + putSessionReturns struct { + result1 error + } + putSessionReturnsOnCall map[int]struct { + result1 error + } + RunViewStub func(viewa.View, ...viewa.RunViewOption) (interface{}, error) + runViewMutex sync.RWMutex + runViewArgsForCall []struct { + arg1 viewa.View + arg2 []viewa.RunViewOption + } + runViewReturns struct { + result1 interface{} + result2 error + } + runViewReturnsOnCall map[int]struct { + result1 interface{} + result2 error + } + SessionStub func() viewa.Session + sessionMutex sync.RWMutex + sessionArgsForCall []struct { + } + sessionReturns struct { + result1 viewa.Session + } + sessionReturnsOnCall map[int]struct { + result1 viewa.Session + } + StartSpanFromStub func(context.Context, string, ...trace.SpanStartOption) (context.Context, trace.Span) + startSpanFromMutex sync.RWMutex + startSpanFromArgsForCall []struct { + arg1 context.Context + arg2 string + arg3 []trace.SpanStartOption + } + startSpanFromReturns struct { + result1 context.Context + result2 trace.Span + } + startSpanFromReturnsOnCall map[int]struct { + result1 context.Context + result2 trace.Span + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *ParentContext) Cleanup() { + fake.cleanupMutex.Lock() + fake.cleanupArgsForCall = append(fake.cleanupArgsForCall, struct { + }{}) + stub := fake.CleanupStub + fake.recordInvocation("Cleanup", []interface{}{}) + fake.cleanupMutex.Unlock() + if stub != nil { + fake.CleanupStub() + } +} + +func (fake *ParentContext) CleanupCallCount() int { + fake.cleanupMutex.RLock() + defer fake.cleanupMutex.RUnlock() + return len(fake.cleanupArgsForCall) +} + +func (fake *ParentContext) CleanupCalls(stub func()) { + fake.cleanupMutex.Lock() + defer fake.cleanupMutex.Unlock() + fake.CleanupStub = stub +} + +func (fake *ParentContext) Context() context.Context { + fake.contextMutex.Lock() + ret, specificReturn := fake.contextReturnsOnCall[len(fake.contextArgsForCall)] + fake.contextArgsForCall = append(fake.contextArgsForCall, struct { + }{}) + stub := fake.ContextStub + fakeReturns := fake.contextReturns + fake.recordInvocation("Context", []interface{}{}) + fake.contextMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *ParentContext) ContextCallCount() int { + fake.contextMutex.RLock() + defer fake.contextMutex.RUnlock() + return len(fake.contextArgsForCall) +} + +func (fake *ParentContext) ContextCalls(stub func() context.Context) { + fake.contextMutex.Lock() + defer fake.contextMutex.Unlock() + fake.ContextStub = stub +} + +func (fake *ParentContext) ContextReturns(result1 context.Context) { + fake.contextMutex.Lock() + defer fake.contextMutex.Unlock() + fake.ContextStub = nil + fake.contextReturns = struct { + result1 context.Context + }{result1} +} + +func (fake *ParentContext) ContextReturnsOnCall(i int, result1 context.Context) { + fake.contextMutex.Lock() + defer fake.contextMutex.Unlock() + fake.ContextStub = nil + if fake.contextReturnsOnCall == nil { + fake.contextReturnsOnCall = make(map[int]struct { + result1 context.Context + }) + } + fake.contextReturnsOnCall[i] = struct { + result1 context.Context + }{result1} +} + +func (fake *ParentContext) Dispose() { + fake.disposeMutex.Lock() + fake.disposeArgsForCall = append(fake.disposeArgsForCall, struct { + }{}) + stub := fake.DisposeStub + fake.recordInvocation("Dispose", []interface{}{}) + fake.disposeMutex.Unlock() + if stub != nil { + fake.DisposeStub() + } +} + +func (fake *ParentContext) DisposeCallCount() int { + fake.disposeMutex.RLock() + defer fake.disposeMutex.RUnlock() + return len(fake.disposeArgsForCall) +} + +func (fake *ParentContext) DisposeCalls(stub func()) { + fake.disposeMutex.Lock() + defer fake.disposeMutex.Unlock() + fake.DisposeStub = stub +} + +func (fake *ParentContext) GetService(arg1 interface{}) (interface{}, error) { + fake.getServiceMutex.Lock() + ret, specificReturn := fake.getServiceReturnsOnCall[len(fake.getServiceArgsForCall)] + fake.getServiceArgsForCall = append(fake.getServiceArgsForCall, struct { + arg1 interface{} + }{arg1}) + stub := fake.GetServiceStub + fakeReturns := fake.getServiceReturns + fake.recordInvocation("GetService", []interface{}{arg1}) + fake.getServiceMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *ParentContext) GetServiceCallCount() int { + fake.getServiceMutex.RLock() + defer fake.getServiceMutex.RUnlock() + return len(fake.getServiceArgsForCall) +} + +func (fake *ParentContext) GetServiceCalls(stub func(interface{}) (interface{}, error)) { + fake.getServiceMutex.Lock() + defer fake.getServiceMutex.Unlock() + fake.GetServiceStub = stub +} + +func (fake *ParentContext) GetServiceArgsForCall(i int) interface{} { + fake.getServiceMutex.RLock() + defer fake.getServiceMutex.RUnlock() + argsForCall := fake.getServiceArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *ParentContext) GetServiceReturns(result1 interface{}, result2 error) { + fake.getServiceMutex.Lock() + defer fake.getServiceMutex.Unlock() + fake.GetServiceStub = nil + fake.getServiceReturns = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *ParentContext) GetServiceReturnsOnCall(i int, result1 interface{}, result2 error) { + fake.getServiceMutex.Lock() + defer fake.getServiceMutex.Unlock() + fake.GetServiceStub = nil + if fake.getServiceReturnsOnCall == nil { + fake.getServiceReturnsOnCall = make(map[int]struct { + result1 interface{} + result2 error + }) + } + fake.getServiceReturnsOnCall[i] = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *ParentContext) GetSession(arg1 viewa.View, arg2 viewa.Identity, arg3 ...viewa.View) (viewa.Session, error) { + fake.getSessionMutex.Lock() + ret, specificReturn := fake.getSessionReturnsOnCall[len(fake.getSessionArgsForCall)] + fake.getSessionArgsForCall = append(fake.getSessionArgsForCall, struct { + arg1 viewa.View + arg2 viewa.Identity + arg3 []viewa.View + }{arg1, arg2, arg3}) + stub := fake.GetSessionStub + fakeReturns := fake.getSessionReturns + fake.recordInvocation("GetSession", []interface{}{arg1, arg2, arg3}) + fake.getSessionMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3...) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *ParentContext) GetSessionCallCount() int { + fake.getSessionMutex.RLock() + defer fake.getSessionMutex.RUnlock() + return len(fake.getSessionArgsForCall) +} + +func (fake *ParentContext) GetSessionCalls(stub func(viewa.View, viewa.Identity, ...viewa.View) (viewa.Session, error)) { + fake.getSessionMutex.Lock() + defer fake.getSessionMutex.Unlock() + fake.GetSessionStub = stub +} + +func (fake *ParentContext) GetSessionArgsForCall(i int) (viewa.View, viewa.Identity, []viewa.View) { + fake.getSessionMutex.RLock() + defer fake.getSessionMutex.RUnlock() + argsForCall := fake.getSessionArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *ParentContext) GetSessionReturns(result1 viewa.Session, result2 error) { + fake.getSessionMutex.Lock() + defer fake.getSessionMutex.Unlock() + fake.GetSessionStub = nil + fake.getSessionReturns = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *ParentContext) GetSessionReturnsOnCall(i int, result1 viewa.Session, result2 error) { + fake.getSessionMutex.Lock() + defer fake.getSessionMutex.Unlock() + fake.GetSessionStub = nil + if fake.getSessionReturnsOnCall == nil { + fake.getSessionReturnsOnCall = make(map[int]struct { + result1 viewa.Session + result2 error + }) + } + fake.getSessionReturnsOnCall[i] = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *ParentContext) GetSessionByID(arg1 string, arg2 viewa.Identity) (viewa.Session, error) { + fake.getSessionByIDMutex.Lock() + ret, specificReturn := fake.getSessionByIDReturnsOnCall[len(fake.getSessionByIDArgsForCall)] + fake.getSessionByIDArgsForCall = append(fake.getSessionByIDArgsForCall, struct { + arg1 string + arg2 viewa.Identity + }{arg1, arg2}) + stub := fake.GetSessionByIDStub + fakeReturns := fake.getSessionByIDReturns + fake.recordInvocation("GetSessionByID", []interface{}{arg1, arg2}) + fake.getSessionByIDMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *ParentContext) GetSessionByIDCallCount() int { + fake.getSessionByIDMutex.RLock() + defer fake.getSessionByIDMutex.RUnlock() + return len(fake.getSessionByIDArgsForCall) +} + +func (fake *ParentContext) GetSessionByIDCalls(stub func(string, viewa.Identity) (viewa.Session, error)) { + fake.getSessionByIDMutex.Lock() + defer fake.getSessionByIDMutex.Unlock() + fake.GetSessionByIDStub = stub +} + +func (fake *ParentContext) GetSessionByIDArgsForCall(i int) (string, viewa.Identity) { + fake.getSessionByIDMutex.RLock() + defer fake.getSessionByIDMutex.RUnlock() + argsForCall := fake.getSessionByIDArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *ParentContext) GetSessionByIDReturns(result1 viewa.Session, result2 error) { + fake.getSessionByIDMutex.Lock() + defer fake.getSessionByIDMutex.Unlock() + fake.GetSessionByIDStub = nil + fake.getSessionByIDReturns = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *ParentContext) GetSessionByIDReturnsOnCall(i int, result1 viewa.Session, result2 error) { + fake.getSessionByIDMutex.Lock() + defer fake.getSessionByIDMutex.Unlock() + fake.GetSessionByIDStub = nil + if fake.getSessionByIDReturnsOnCall == nil { + fake.getSessionByIDReturnsOnCall = make(map[int]struct { + result1 viewa.Session + result2 error + }) + } + fake.getSessionByIDReturnsOnCall[i] = struct { + result1 viewa.Session + result2 error + }{result1, result2} +} + +func (fake *ParentContext) ID() string { + fake.iDMutex.Lock() + ret, specificReturn := fake.iDReturnsOnCall[len(fake.iDArgsForCall)] + fake.iDArgsForCall = append(fake.iDArgsForCall, struct { + }{}) + stub := fake.IDStub + fakeReturns := fake.iDReturns + fake.recordInvocation("ID", []interface{}{}) + fake.iDMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *ParentContext) IDCallCount() int { + fake.iDMutex.RLock() + defer fake.iDMutex.RUnlock() + return len(fake.iDArgsForCall) +} + +func (fake *ParentContext) IDCalls(stub func() string) { + fake.iDMutex.Lock() + defer fake.iDMutex.Unlock() + fake.IDStub = stub +} + +func (fake *ParentContext) IDReturns(result1 string) { + fake.iDMutex.Lock() + defer fake.iDMutex.Unlock() + fake.IDStub = nil + fake.iDReturns = struct { + result1 string + }{result1} +} + +func (fake *ParentContext) IDReturnsOnCall(i int, result1 string) { + fake.iDMutex.Lock() + defer fake.iDMutex.Unlock() + fake.IDStub = nil + if fake.iDReturnsOnCall == nil { + fake.iDReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.iDReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *ParentContext) Initiator() viewa.View { + fake.initiatorMutex.Lock() + ret, specificReturn := fake.initiatorReturnsOnCall[len(fake.initiatorArgsForCall)] + fake.initiatorArgsForCall = append(fake.initiatorArgsForCall, struct { + }{}) + stub := fake.InitiatorStub + fakeReturns := fake.initiatorReturns + fake.recordInvocation("Initiator", []interface{}{}) + fake.initiatorMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *ParentContext) InitiatorCallCount() int { + fake.initiatorMutex.RLock() + defer fake.initiatorMutex.RUnlock() + return len(fake.initiatorArgsForCall) +} + +func (fake *ParentContext) InitiatorCalls(stub func() viewa.View) { + fake.initiatorMutex.Lock() + defer fake.initiatorMutex.Unlock() + fake.InitiatorStub = stub +} + +func (fake *ParentContext) InitiatorReturns(result1 viewa.View) { + fake.initiatorMutex.Lock() + defer fake.initiatorMutex.Unlock() + fake.InitiatorStub = nil + fake.initiatorReturns = struct { + result1 viewa.View + }{result1} +} + +func (fake *ParentContext) InitiatorReturnsOnCall(i int, result1 viewa.View) { + fake.initiatorMutex.Lock() + defer fake.initiatorMutex.Unlock() + fake.InitiatorStub = nil + if fake.initiatorReturnsOnCall == nil { + fake.initiatorReturnsOnCall = make(map[int]struct { + result1 viewa.View + }) + } + fake.initiatorReturnsOnCall[i] = struct { + result1 viewa.View + }{result1} +} + +func (fake *ParentContext) IsMe(arg1 viewa.Identity) bool { + fake.isMeMutex.Lock() + ret, specificReturn := fake.isMeReturnsOnCall[len(fake.isMeArgsForCall)] + fake.isMeArgsForCall = append(fake.isMeArgsForCall, struct { + arg1 viewa.Identity + }{arg1}) + stub := fake.IsMeStub + fakeReturns := fake.isMeReturns + fake.recordInvocation("IsMe", []interface{}{arg1}) + fake.isMeMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *ParentContext) IsMeCallCount() int { + fake.isMeMutex.RLock() + defer fake.isMeMutex.RUnlock() + return len(fake.isMeArgsForCall) +} + +func (fake *ParentContext) IsMeCalls(stub func(viewa.Identity) bool) { + fake.isMeMutex.Lock() + defer fake.isMeMutex.Unlock() + fake.IsMeStub = stub +} + +func (fake *ParentContext) IsMeArgsForCall(i int) viewa.Identity { + fake.isMeMutex.RLock() + defer fake.isMeMutex.RUnlock() + argsForCall := fake.isMeArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *ParentContext) IsMeReturns(result1 bool) { + fake.isMeMutex.Lock() + defer fake.isMeMutex.Unlock() + fake.IsMeStub = nil + fake.isMeReturns = struct { + result1 bool + }{result1} +} + +func (fake *ParentContext) IsMeReturnsOnCall(i int, result1 bool) { + fake.isMeMutex.Lock() + defer fake.isMeMutex.Unlock() + fake.IsMeStub = nil + if fake.isMeReturnsOnCall == nil { + fake.isMeReturnsOnCall = make(map[int]struct { + result1 bool + }) + } + fake.isMeReturnsOnCall[i] = struct { + result1 bool + }{result1} +} + +func (fake *ParentContext) Me() viewa.Identity { + fake.meMutex.Lock() + ret, specificReturn := fake.meReturnsOnCall[len(fake.meArgsForCall)] + fake.meArgsForCall = append(fake.meArgsForCall, struct { + }{}) + stub := fake.MeStub + fakeReturns := fake.meReturns + fake.recordInvocation("Me", []interface{}{}) + fake.meMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *ParentContext) MeCallCount() int { + fake.meMutex.RLock() + defer fake.meMutex.RUnlock() + return len(fake.meArgsForCall) +} + +func (fake *ParentContext) MeCalls(stub func() viewa.Identity) { + fake.meMutex.Lock() + defer fake.meMutex.Unlock() + fake.MeStub = stub +} + +func (fake *ParentContext) MeReturns(result1 viewa.Identity) { + fake.meMutex.Lock() + defer fake.meMutex.Unlock() + fake.MeStub = nil + fake.meReturns = struct { + result1 viewa.Identity + }{result1} +} + +func (fake *ParentContext) MeReturnsOnCall(i int, result1 viewa.Identity) { + fake.meMutex.Lock() + defer fake.meMutex.Unlock() + fake.MeStub = nil + if fake.meReturnsOnCall == nil { + fake.meReturnsOnCall = make(map[int]struct { + result1 viewa.Identity + }) + } + fake.meReturnsOnCall[i] = struct { + result1 viewa.Identity + }{result1} +} + +func (fake *ParentContext) OnError(arg1 func()) { + fake.onErrorMutex.Lock() + fake.onErrorArgsForCall = append(fake.onErrorArgsForCall, struct { + arg1 func() + }{arg1}) + stub := fake.OnErrorStub + fake.recordInvocation("OnError", []interface{}{arg1}) + fake.onErrorMutex.Unlock() + if stub != nil { + fake.OnErrorStub(arg1) + } +} + +func (fake *ParentContext) OnErrorCallCount() int { + fake.onErrorMutex.RLock() + defer fake.onErrorMutex.RUnlock() + return len(fake.onErrorArgsForCall) +} + +func (fake *ParentContext) OnErrorCalls(stub func(func())) { + fake.onErrorMutex.Lock() + defer fake.onErrorMutex.Unlock() + fake.OnErrorStub = stub +} + +func (fake *ParentContext) OnErrorArgsForCall(i int) func() { + fake.onErrorMutex.RLock() + defer fake.onErrorMutex.RUnlock() + argsForCall := fake.onErrorArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *ParentContext) PutSession(arg1 viewa.View, arg2 viewa.Identity, arg3 viewa.Session) error { + fake.putSessionMutex.Lock() + ret, specificReturn := fake.putSessionReturnsOnCall[len(fake.putSessionArgsForCall)] + fake.putSessionArgsForCall = append(fake.putSessionArgsForCall, struct { + arg1 viewa.View + arg2 viewa.Identity + arg3 viewa.Session + }{arg1, arg2, arg3}) + stub := fake.PutSessionStub + fakeReturns := fake.putSessionReturns + fake.recordInvocation("PutSession", []interface{}{arg1, arg2, arg3}) + fake.putSessionMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *ParentContext) PutSessionCallCount() int { + fake.putSessionMutex.RLock() + defer fake.putSessionMutex.RUnlock() + return len(fake.putSessionArgsForCall) +} + +func (fake *ParentContext) PutSessionCalls(stub func(viewa.View, viewa.Identity, viewa.Session) error) { + fake.putSessionMutex.Lock() + defer fake.putSessionMutex.Unlock() + fake.PutSessionStub = stub +} + +func (fake *ParentContext) PutSessionArgsForCall(i int) (viewa.View, viewa.Identity, viewa.Session) { + fake.putSessionMutex.RLock() + defer fake.putSessionMutex.RUnlock() + argsForCall := fake.putSessionArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *ParentContext) PutSessionReturns(result1 error) { + fake.putSessionMutex.Lock() + defer fake.putSessionMutex.Unlock() + fake.PutSessionStub = nil + fake.putSessionReturns = struct { + result1 error + }{result1} +} + +func (fake *ParentContext) PutSessionReturnsOnCall(i int, result1 error) { + fake.putSessionMutex.Lock() + defer fake.putSessionMutex.Unlock() + fake.PutSessionStub = nil + if fake.putSessionReturnsOnCall == nil { + fake.putSessionReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.putSessionReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *ParentContext) RunView(arg1 viewa.View, arg2 ...viewa.RunViewOption) (interface{}, error) { + fake.runViewMutex.Lock() + ret, specificReturn := fake.runViewReturnsOnCall[len(fake.runViewArgsForCall)] + fake.runViewArgsForCall = append(fake.runViewArgsForCall, struct { + arg1 viewa.View + arg2 []viewa.RunViewOption + }{arg1, arg2}) + stub := fake.RunViewStub + fakeReturns := fake.runViewReturns + fake.recordInvocation("RunView", []interface{}{arg1, arg2}) + fake.runViewMutex.Unlock() + if stub != nil { + return stub(arg1, arg2...) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *ParentContext) RunViewCallCount() int { + fake.runViewMutex.RLock() + defer fake.runViewMutex.RUnlock() + return len(fake.runViewArgsForCall) +} + +func (fake *ParentContext) RunViewCalls(stub func(viewa.View, ...viewa.RunViewOption) (interface{}, error)) { + fake.runViewMutex.Lock() + defer fake.runViewMutex.Unlock() + fake.RunViewStub = stub +} + +func (fake *ParentContext) RunViewArgsForCall(i int) (viewa.View, []viewa.RunViewOption) { + fake.runViewMutex.RLock() + defer fake.runViewMutex.RUnlock() + argsForCall := fake.runViewArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *ParentContext) RunViewReturns(result1 interface{}, result2 error) { + fake.runViewMutex.Lock() + defer fake.runViewMutex.Unlock() + fake.RunViewStub = nil + fake.runViewReturns = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *ParentContext) RunViewReturnsOnCall(i int, result1 interface{}, result2 error) { + fake.runViewMutex.Lock() + defer fake.runViewMutex.Unlock() + fake.RunViewStub = nil + if fake.runViewReturnsOnCall == nil { + fake.runViewReturnsOnCall = make(map[int]struct { + result1 interface{} + result2 error + }) + } + fake.runViewReturnsOnCall[i] = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *ParentContext) Session() viewa.Session { + fake.sessionMutex.Lock() + ret, specificReturn := fake.sessionReturnsOnCall[len(fake.sessionArgsForCall)] + fake.sessionArgsForCall = append(fake.sessionArgsForCall, struct { + }{}) + stub := fake.SessionStub + fakeReturns := fake.sessionReturns + fake.recordInvocation("Session", []interface{}{}) + fake.sessionMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *ParentContext) SessionCallCount() int { + fake.sessionMutex.RLock() + defer fake.sessionMutex.RUnlock() + return len(fake.sessionArgsForCall) +} + +func (fake *ParentContext) SessionCalls(stub func() viewa.Session) { + fake.sessionMutex.Lock() + defer fake.sessionMutex.Unlock() + fake.SessionStub = stub +} + +func (fake *ParentContext) SessionReturns(result1 viewa.Session) { + fake.sessionMutex.Lock() + defer fake.sessionMutex.Unlock() + fake.SessionStub = nil + fake.sessionReturns = struct { + result1 viewa.Session + }{result1} +} + +func (fake *ParentContext) SessionReturnsOnCall(i int, result1 viewa.Session) { + fake.sessionMutex.Lock() + defer fake.sessionMutex.Unlock() + fake.SessionStub = nil + if fake.sessionReturnsOnCall == nil { + fake.sessionReturnsOnCall = make(map[int]struct { + result1 viewa.Session + }) + } + fake.sessionReturnsOnCall[i] = struct { + result1 viewa.Session + }{result1} +} + +func (fake *ParentContext) StartSpanFrom(arg1 context.Context, arg2 string, arg3 ...trace.SpanStartOption) (context.Context, trace.Span) { + fake.startSpanFromMutex.Lock() + ret, specificReturn := fake.startSpanFromReturnsOnCall[len(fake.startSpanFromArgsForCall)] + fake.startSpanFromArgsForCall = append(fake.startSpanFromArgsForCall, struct { + arg1 context.Context + arg2 string + arg3 []trace.SpanStartOption + }{arg1, arg2, arg3}) + stub := fake.StartSpanFromStub + fakeReturns := fake.startSpanFromReturns + fake.recordInvocation("StartSpanFrom", []interface{}{arg1, arg2, arg3}) + fake.startSpanFromMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3...) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *ParentContext) StartSpanFromCallCount() int { + fake.startSpanFromMutex.RLock() + defer fake.startSpanFromMutex.RUnlock() + return len(fake.startSpanFromArgsForCall) +} + +func (fake *ParentContext) StartSpanFromCalls(stub func(context.Context, string, ...trace.SpanStartOption) (context.Context, trace.Span)) { + fake.startSpanFromMutex.Lock() + defer fake.startSpanFromMutex.Unlock() + fake.StartSpanFromStub = stub +} + +func (fake *ParentContext) StartSpanFromArgsForCall(i int) (context.Context, string, []trace.SpanStartOption) { + fake.startSpanFromMutex.RLock() + defer fake.startSpanFromMutex.RUnlock() + argsForCall := fake.startSpanFromArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *ParentContext) StartSpanFromReturns(result1 context.Context, result2 trace.Span) { + fake.startSpanFromMutex.Lock() + defer fake.startSpanFromMutex.Unlock() + fake.StartSpanFromStub = nil + fake.startSpanFromReturns = struct { + result1 context.Context + result2 trace.Span + }{result1, result2} +} + +func (fake *ParentContext) StartSpanFromReturnsOnCall(i int, result1 context.Context, result2 trace.Span) { + fake.startSpanFromMutex.Lock() + defer fake.startSpanFromMutex.Unlock() + fake.StartSpanFromStub = nil + if fake.startSpanFromReturnsOnCall == nil { + fake.startSpanFromReturnsOnCall = make(map[int]struct { + result1 context.Context + result2 trace.Span + }) + } + fake.startSpanFromReturnsOnCall[i] = struct { + result1 context.Context + result2 trace.Span + }{result1, result2} +} + +func (fake *ParentContext) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.cleanupMutex.RLock() + defer fake.cleanupMutex.RUnlock() + fake.contextMutex.RLock() + defer fake.contextMutex.RUnlock() + fake.disposeMutex.RLock() + defer fake.disposeMutex.RUnlock() + fake.getServiceMutex.RLock() + defer fake.getServiceMutex.RUnlock() + fake.getSessionMutex.RLock() + defer fake.getSessionMutex.RUnlock() + fake.getSessionByIDMutex.RLock() + defer fake.getSessionByIDMutex.RUnlock() + fake.iDMutex.RLock() + defer fake.iDMutex.RUnlock() + fake.initiatorMutex.RLock() + defer fake.initiatorMutex.RUnlock() + fake.isMeMutex.RLock() + defer fake.isMeMutex.RUnlock() + fake.meMutex.RLock() + defer fake.meMutex.RUnlock() + fake.onErrorMutex.RLock() + defer fake.onErrorMutex.RUnlock() + fake.putSessionMutex.RLock() + defer fake.putSessionMutex.RUnlock() + fake.runViewMutex.RLock() + defer fake.runViewMutex.RUnlock() + fake.sessionMutex.RLock() + defer fake.sessionMutex.RUnlock() + fake.startSpanFromMutex.RLock() + defer fake.startSpanFromMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *ParentContext) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ view.ParentContext = new(ParentContext) diff --git a/platform/view/services/view/runner.go b/platform/view/services/view/mock/runner.go similarity index 54% rename from platform/view/services/view/runner.go rename to platform/view/services/view/mock/runner.go index 9315e47a0..d6c6a1842 100644 --- a/platform/view/services/view/runner.go +++ b/platform/view/services/view/mock/runner.go @@ -4,7 +4,7 @@ Copyright IBM Corp. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package view +package mock import ( "context" @@ -12,6 +12,7 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/comm/session" + view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace/noop" @@ -25,61 +26,61 @@ type Responders struct { Channel *session.LocalBidirectionalChannel } -type MockContext struct { +type DelegatedContext struct { Ctx view.Context responders []*Responders } -func (c *MockContext) StartSpanFrom(context.Context, string, ...trace.SpanStartOption) (context.Context, trace.Span) { +func (c *DelegatedContext) StartSpanFrom(context.Context, string, ...trace.SpanStartOption) (context.Context, trace.Span) { return c.Context(), noop.Span{} } -func (c *MockContext) StartSpan(string, ...trace.SpanStartOption) trace.Span { +func (c *DelegatedContext) StartSpan(string, ...trace.SpanStartOption) trace.Span { return noop.Span{} } -func (c *MockContext) GetService(v interface{}) (interface{}, error) { +func (c *DelegatedContext) GetService(v interface{}) (interface{}, error) { return c.Ctx.GetService(v) } -func (c *MockContext) ID() string { +func (c *DelegatedContext) ID() string { return c.Ctx.ID() } -func (c *MockContext) RunView(view view.View, opts ...view.RunViewOption) (interface{}, error) { +func (c *DelegatedContext) RunView(view view.View, opts ...view.RunViewOption) (interface{}, error) { return c.Ctx.RunView(view, opts...) } -func (c *MockContext) Me() view.Identity { +func (c *DelegatedContext) Me() view.Identity { return c.Ctx.Me() } -func (c *MockContext) IsMe(id view.Identity) bool { +func (c *DelegatedContext) IsMe(id view.Identity) bool { return c.Ctx.IsMe(id) } -func (c *MockContext) Initiator() view.View { +func (c *DelegatedContext) Initiator() view.View { return c.Ctx.Initiator() } -func (c *MockContext) GetSessionByID(id string, party view.Identity) (view.Session, error) { +func (c *DelegatedContext) GetSessionByID(id string, party view.Identity) (view.Session, error) { // TODO: check among the responders return c.Ctx.GetSessionByID(id, party) } -func (c *MockContext) Session() view.Session { +func (c *DelegatedContext) Session() view.Session { return c.Ctx.Session() } -func (c *MockContext) Context() context.Context { +func (c *DelegatedContext) Context() context.Context { return c.Ctx.Context() } -func (c *MockContext) OnError(callback func()) { +func (c *DelegatedContext) OnError(callback func()) { c.Ctx.OnError(callback) } -func (c *MockContext) GetSession(caller view.View, party view.Identity, boundToViews ...view.View) (view.Session, error) { +func (c *DelegatedContext) GetSession(caller view.View, party view.Identity, boundToViews ...view.View) (view.Session, error) { for _, responder := range c.responders { if responder.InitiatorView == caller && responder.ResponderID.Equal(party) { responder.Lock.RLock() @@ -103,7 +104,7 @@ func (c *MockContext) GetSession(caller view.View, party view.Identity, boundToV } left := biChannel.LeftSession() right := biChannel.RightSession() - RunView(c, responder.ResponderView, view.AsResponder(right)) + view2.RunView(c, responder.ResponderView, view.AsResponder(right)) responder.Channel = biChannel return left, nil @@ -113,30 +114,10 @@ func (c *MockContext) GetSession(caller view.View, party view.Identity, boundToV return c.Ctx.GetSession(caller, party) } -func (c *MockContext) RespondToAs(initiator view.View, responder view.Identity, r view.View) { +func (c *DelegatedContext) RespondToAs(initiator view.View, responder view.Identity, r view.View) { c.responders = append(c.responders, &Responders{ InitiatorView: initiator, ResponderID: responder, ResponderView: r, }) } - -// RunView runs passed view within the passed context and using the passed options in a separate goroutine -func RunView(context view.Context, view view.View, opts ...view.RunViewOption) { - defer func() { - if r := recover(); r != nil { - logger.Debugf("panic in RunView: %v", r) - } - }() - go func() { - defer func() { - if r := recover(); r != nil { - logger.Debugf("panic in RunView: %v", r) - } - }() - _, err := context.RunView(view, opts...) - if err != nil { - logger.Errorf("failed to run view: %s", err) - } - }() -} diff --git a/platform/view/services/view/mock/view.go b/platform/view/services/view/mock/view.go new file mode 100644 index 000000000..6cc880ecb --- /dev/null +++ b/platform/view/services/view/mock/view.go @@ -0,0 +1,117 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package mock + +import ( + "sync" + + "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view" + viewa "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" +) + +type View struct { + CallStub func(viewa.Context) (interface{}, error) + callMutex sync.RWMutex + callArgsForCall []struct { + arg1 viewa.Context + } + callReturns struct { + result1 interface{} + result2 error + } + callReturnsOnCall map[int]struct { + result1 interface{} + result2 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *View) Call(arg1 viewa.Context) (interface{}, error) { + fake.callMutex.Lock() + ret, specificReturn := fake.callReturnsOnCall[len(fake.callArgsForCall)] + fake.callArgsForCall = append(fake.callArgsForCall, struct { + arg1 viewa.Context + }{arg1}) + stub := fake.CallStub + fakeReturns := fake.callReturns + fake.recordInvocation("Call", []interface{}{arg1}) + fake.callMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *View) CallCallCount() int { + fake.callMutex.RLock() + defer fake.callMutex.RUnlock() + return len(fake.callArgsForCall) +} + +func (fake *View) CallCalls(stub func(viewa.Context) (interface{}, error)) { + fake.callMutex.Lock() + defer fake.callMutex.Unlock() + fake.CallStub = stub +} + +func (fake *View) CallArgsForCall(i int) viewa.Context { + fake.callMutex.RLock() + defer fake.callMutex.RUnlock() + argsForCall := fake.callArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *View) CallReturns(result1 interface{}, result2 error) { + fake.callMutex.Lock() + defer fake.callMutex.Unlock() + fake.CallStub = nil + fake.callReturns = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *View) CallReturnsOnCall(i int, result1 interface{}, result2 error) { + fake.callMutex.Lock() + defer fake.callMutex.Unlock() + fake.CallStub = nil + if fake.callReturnsOnCall == nil { + fake.callReturnsOnCall = make(map[int]struct { + result1 interface{} + result2 error + }) + } + fake.callReturnsOnCall[i] = struct { + result1 interface{} + result2 error + }{result1, result2} +} + +func (fake *View) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.callMutex.RLock() + defer fake.callMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *View) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ view.View = new(View) diff --git a/platform/view/services/view/view.go b/platform/view/services/view/view.go index c8aa14ea2..de6b00a15 100644 --- a/platform/view/services/view/view.go +++ b/platform/view/services/view/view.go @@ -7,9 +7,23 @@ SPDX-License-Identifier: Apache-2.0 package view import ( + "runtime/debug" + + "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" + "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/tracing" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) +//go:generate counterfeiter -o mock/context.go -fake-name Context . ViewContext +type ViewContext = view.Context + +// View is an alias for View +// +//go:generate counterfeiter -o mock/view.go -fake-name View . View +type View = view.View + // RunCall is a shortcut for `context.RunView(nil, view.WithViewCall(v))` and can be used to run a view call in a given context. func RunCall(context view.Context, v func(context view.Context) (interface{}, error)) (interface{}, error) { return context.RunView( @@ -21,7 +35,7 @@ func RunCall(context view.Context, v func(context view.Context) (interface{}, er // Initiate initiates a new protocol whose initiator's view is the passed one. // The execution happens in a freshly created context. // This is a shortcut for `view.GetManager(context).InitiateView(initiator)`. -func Initiate(context view.Context, initiator view.View) (interface{}, error) { +func Initiate(context view.Context, initiator View) (interface{}, error) { m, err := GetManager(context) if err != nil { return nil, err @@ -43,7 +57,7 @@ func AsResponder(context view.Context, session view.Session, v func(context view // Recall that an initiator is characterized by having an initiator (`context.Initiator()`) set when the initiator is instantiated. // AsInitiatorCall sets context.Initiator() to the passed initiator, and executes the passed view call. // TODO: what happens to the sessions already openend with a different initiator (maybe an empty one)? -func AsInitiatorCall(context view.Context, initiator view.View, v func(context view.Context) (interface{}, error)) (interface{}, error) { +func AsInitiatorCall(context view.Context, initiator View, v func(context view.Context) (interface{}, error)) (interface{}, error) { return context.RunView( initiator, view.WithViewCall(v), @@ -54,9 +68,106 @@ func AsInitiatorCall(context view.Context, initiator view.View, v func(context v // AsInitiatorView can be used by a responder to behave temporarily as an initiator. // Recall that an initiator is characterized by having an initiator (`context.Initiator()`) set when the initiator is instantiated. // AsInitiatorView sets context.Initiator() to the passed initiator, and executes it. -func AsInitiatorView(context view.Context, initiator view.View) (interface{}, error) { +func AsInitiatorView(context view.Context, initiator View) (interface{}, error) { return context.RunView( initiator, view.AsInitiator(), ) } + +// RunViewNow invokes the Call function of the given view. +// The view context used to the run view is either ctx or the one extracted from the options (see view.WithContext), if present. +func RunViewNow(ctx ParentContext, v View, opts ...view.RunViewOption) (res interface{}, err error) { + options, err := view.CompileRunViewOptions(opts...) + if err != nil { + return nil, errors.Wrap(err, "failed compiling options") + } + var initiator View + if options.AsInitiator { + initiator = v + } + + goContext := ctx.Context() + if options.Context != nil { + goContext = options.Context + } + + logger.DebugfContext(goContext, "Start view %s", GetName(v)) + newCtx, span := ctx.StartSpanFrom(goContext, GetName(v), tracing.WithAttributes( + tracing.String(ViewLabel, GetIdentifier(v)), + tracing.String(InitiatorViewLabel, GetIdentifier(initiator)), + ), trace.WithSpanKind(trace.SpanKindInternal)) + defer span.End() + + var cc ParentContext + if options.SameContext { + cc = WrapContext(ctx, newCtx) + } else { + if options.AsInitiator { + cc = NewChildContextFromParentAndInitiator(WrapContext(ctx, newCtx), initiator) + // register options.Session under initiator + contextSession := ctx.Session() + if contextSession == nil { + return nil, errors.Errorf("cannot convert a non-responder context to an initiator context") + } + if err := cc.PutSession(initiator, contextSession.Info().Caller, contextSession); err != nil { + return nil, errors.Wrapf(err, "failed registering default session as initiated by [%s:%s]", initiator, contextSession.Info().Caller) + } + } else { + cc = NewChildContext(WrapContext(ctx, newCtx), options.Session, initiator) + } + } + + defer func() { + if r := recover(); r != nil { + cc.Cleanup() + res = nil + + logger.Errorf("caught panic while running view with [%v][%s]", r, debug.Stack()) + + switch e := r.(type) { + case error: + err = errors.WithMessage(e, "caught panic") + case string: + err = errors.New(e) + default: + err = errors.Errorf("caught panic [%v]", e) + } + } + }() + + if v == nil && options.Call == nil { + return nil, errors.Errorf("no view passed") + } + if options.Call != nil { + res, err = options.Call(cc) + } else { + res, err = v.Call(cc) + } + span.SetAttributes(attribute.Bool(SuccessLabel, err != nil)) + if err != nil { + cc.Cleanup() + return nil, err + } + return res, err +} + +// RunView runs passed view within the passed context and using the passed options in a separate goroutine +func RunView(context view.Context, view View, opts ...view.RunViewOption) { + defer func() { + if r := recover(); r != nil { + logger.Debugf("panic in RunView: %v", r) + } + }() + go func() { + defer func() { + if r := recover(); r != nil { + logger.Debugf("panic in RunView: %v", r) + } + }() + _, err := context.RunView(view, opts...) + if err != nil { + logger.Errorf("failed to run view: %s", err) + } + }() +} diff --git a/platform/view/services/view/view_test.go b/platform/view/services/view/view_test.go new file mode 100644 index 000000000..cb7c0e844 --- /dev/null +++ b/platform/view/services/view/view_test.go @@ -0,0 +1,119 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package view_test + +import ( + "context" + "errors" + "testing" + + "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view" + "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view/mock" + view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace/noop" +) + +type testKey string + +func TestRunViewNow(t *testing.T) { + v := &mock.View{} + v.CallStub = func(ctx view2.Context) (interface{}, error) { + value, ok := ctx.Context().Value(v).(testKey) + if !ok { + panic("value is not a string") + } + return value, nil + } + + ctx := t.Context() + ctx = context.WithValue(ctx, v, testKey("test")) + + parent := &mock.ParentContext{} + parent.ContextReturns(t.Context()) + parent.StartSpanFromReturns(ctx, &noop.Span{}) + value, err := view.RunViewNow(parent, v, view2.WithContext(ctx)) + require.NoError(t, err) + assert.Equal(t, testKey("test"), value) +} + +func TestRunViewNow_CallOption(t *testing.T) { + parent := &mock.ParentContext{} + ctx := t.Context() + ctx = context.WithValue(ctx, testKey("k"), "val") + parent.ContextReturns(t.Context()) + parent.StartSpanFromReturns(ctx, &noop.Span{}) + + call := func(c view2.Context) (interface{}, error) { + return c.Context().Value(testKey("k")), nil + } + + res, err := view.RunViewNow(parent, nil, view2.WithViewCall(call), view2.WithContext(ctx)) + require.NoError(t, err) + assert.Equal(t, "val", res) +} + +func TestRunViewNow_AsInitiator_NoSession(t *testing.T) { + v := &mock.View{} + parent := &mock.ParentContext{} + parent.ContextReturns(t.Context()) + parent.StartSpanFromReturns(t.Context(), &noop.Span{}) + // ensure Session() returns nil to trigger the error path + parent.SessionReturns(nil) + + _, err := view.RunViewNow(parent, v, view2.AsInitiator()) + require.Error(t, err) + assert.Contains(t, err.Error(), "cannot convert a non-responder context to an initiator context") +} + +func TestRunViewNow_AsInitiator_PutSessionError(t *testing.T) { + v := &mock.View{} + parent := &mock.ParentContext{} + parent.ContextReturns(t.Context()) + parent.StartSpanFromReturns(t.Context(), &noop.Span{}) + + // create a mock session with Info returning a caller + s := &mock.Session{} + s.InfoReturns(view2.SessionInfo{Caller: view2.Identity("caller1")}) + parent.SessionReturns(s) + parent.PutSessionReturns(errors.New("put failed")) + + _, err := view.RunViewNow(parent, v, view2.AsInitiator()) + require.Error(t, err) + assert.Contains(t, err.Error(), "failed registering default session as initiated by") +} + +func TestRunViewNow_PanicInView_CallsCleanupAndReturnsError(t *testing.T) { + v := &mock.View{} + v.CallStub = func(ctx view2.Context) (interface{}, error) { + panic(errors.New("boom")) + } + + parent := &mock.ParentContext{} + parent.ContextReturns(t.Context()) + parent.StartSpanFromReturns(t.Context(), &noop.Span{}) + + called := false + parent.CleanupCalls(func() { called = true }) + + // use SameContext so cc becomes WrapContext(ctx, newCtx) and Cleanup() calls parent.Cleanup + _, err := view.RunViewNow(parent, v, view2.WithSameContext()) + require.Error(t, err) + assert.Contains(t, err.Error(), "caught panic") + assert.True(t, called, "expected parent.Cleanup to be invoked") +} + +func TestRunViewNow_NoViewAndNoCall(t *testing.T) { + parent := &mock.ParentContext{} + parent.ContextReturns(t.Context()) + parent.StartSpanFromReturns(t.Context(), &noop.Span{}) + + _, err := view.RunViewNow(parent, nil) + require.Error(t, err) + assert.Contains(t, err.Error(), "no view passed") +} diff --git a/platform/view/services/view/wrapper.go b/platform/view/services/view/wrapper.go index 96b0d8d93..4bc78a540 100644 --- a/platform/view/services/view/wrapper.go +++ b/platform/view/services/view/wrapper.go @@ -8,116 +8,23 @@ package view import ( "context" - - "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" - "go.opentelemetry.io/otel/trace" ) -type disposableContext interface { - view.Context - Dispose() -} - -type childContext struct { - ParentContext localContext - - session view.Session - initiator view.View - errorCallbackFuncs []func() -} - -func (w *childContext) StartSpanFrom(c context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { - return w.ParentContext.StartSpanFrom(c, name, opts...) -} - -func (w *childContext) GetService(v interface{}) (interface{}, error) { - return w.ParentContext.GetService(v) -} - -func (w *childContext) PutService(v interface{}) error { - mutableContext, ok := w.ParentContext.(view.MutableContext) - if ok { - return mutableContext.PutService(v) - } - return nil -} - -func (w *childContext) ID() string { - return w.ParentContext.ID() -} - -func (w *childContext) Me() view.Identity { - return w.ParentContext.Me() -} - -func (w *childContext) IsMe(id view.Identity) bool { - return w.ParentContext.IsMe(id) -} - -func (w *childContext) GetSession(caller view.View, party view.Identity, boundToViews ...view.View) (view.Session, error) { - return w.ParentContext.GetSession(caller, party, boundToViews...) -} - -func (w *childContext) GetSessionByID(id string, party view.Identity) (view.Session, error) { - return w.ParentContext.GetSessionByID(id, party) -} - -func (w *childContext) Context() context.Context { - return w.ParentContext.Context() -} - -func (w *childContext) Session() view.Session { - if w.session == nil { - return w.ParentContext.Session() - } - return w.session -} - -func (w *childContext) ResetSessions() error { - mutableContext, ok := w.ParentContext.(view.MutableContext) - if ok { - return mutableContext.ResetSessions() - } - return nil -} - -func (w *childContext) Initiator() view.View { - if w.initiator == nil { - return w.ParentContext.Initiator() - } - return w.initiator -} - -func (w *childContext) OnError(f func()) { - w.errorCallbackFuncs = append(w.errorCallbackFuncs, f) -} - -func (w *childContext) RunView(v view.View, opts ...view.RunViewOption) (res interface{}, err error) { - return runViewOn(v, opts, w) -} - -func (w *childContext) Dispose() { - if w.ParentContext != nil { - w.ParentContext.Dispose() - } -} - -func (w *childContext) PutSession(caller view.View, party view.Identity, session view.Session) error { - return w.ParentContext.PutSession(caller, party, session) +// WrappedContext wraps an existing view context to provider a different context.Context +type WrappedContext struct { + ParentContext + goContext context.Context } -func (w *childContext) cleanup() { - logger.Debugf("cleaning up child context [%s][%d]", w.ID(), len(w.errorCallbackFuncs)) - for _, callbackFunc := range w.errorCallbackFuncs { - w.safeInvoke(callbackFunc) +// WrapContext returns a new WrappedContext for the given arguments +func WrapContext(ctx ParentContext, goContext context.Context) *WrappedContext { + return &WrappedContext{ + ParentContext: ctx, + goContext: goContext, } } -func (w *childContext) safeInvoke(f func()) { - defer func() { - if r := recover(); r != nil { - logger.Debugf("function [%s] panicked [%s]", f, r) - } - }() - f() +// Context returns the overrode go context +func (c *WrappedContext) Context() context.Context { + return c.goContext } diff --git a/platform/view/view/context.go b/platform/view/view/context.go index 31969232c..ac6d6f453 100644 --- a/platform/view/view/context.go +++ b/platform/view/view/context.go @@ -18,6 +18,7 @@ type RunViewOptions struct { AsInitiator bool Call func(Context) (interface{}, error) SameContext bool + Context context.Context } // CompileRunViewOptions compiles a set of RunViewOption to a RunViewOptions @@ -66,6 +67,15 @@ func WithSameContext() RunViewOption { } } +// WithContext is used to pass a different context to the view +func WithContext(ctx context.Context) RunViewOption { + return func(o *RunViewOptions) error { + o.SameContext = true + o.Context = ctx + return nil + } +} + // MutableContext models a mutable context type MutableContext interface { // ResetSessions disposes all sessions created in this context From a7c1d7a876d66869180f7087b90dc0092f8d82d1 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Sun, 23 Nov 2025 10:18:05 +0100 Subject: [PATCH 2/4] additional comments Signed-off-by: Angelo De Caro --- platform/view/services/view/child.go | 7 +++++++ platform/view/services/view/context.go | 2 ++ platform/view/services/view/view.go | 2 ++ platform/view/view/context.go | 5 +++-- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/platform/view/services/view/child.go b/platform/view/services/view/child.go index 213ae87c8..71810100f 100644 --- a/platform/view/services/view/child.go +++ b/platform/view/services/view/child.go @@ -20,6 +20,9 @@ type ParentContext interface { PutSession(caller view.View, party view.Identity, session view.Session) error } +// ChildContext is a view context with a parent. +// It allows the developer to override session and initiator. +// It also supports error callbacks. type ChildContext struct { Parent ParentContext @@ -28,18 +31,22 @@ type ChildContext struct { errorCallbackFuncs []func() } +// NewChildContextFromParent return a new ChildContext from the given parent func NewChildContextFromParent(parentContext ParentContext) *ChildContext { return NewChildContext(parentContext, nil, nil, nil) } +// NewChildContextFromParentAndSession return a new ChildContext from the given parent and session func NewChildContextFromParentAndSession(parentContext ParentContext, session view.Session) *ChildContext { return NewChildContext(parentContext, session, nil, nil) } +// NewChildContextFromParentAndInitiator return a new ChildContext from the given parent and initiator view func NewChildContextFromParentAndInitiator(parentContext ParentContext, initiator view.View) *ChildContext { return NewChildContext(parentContext, nil, initiator, nil) } +// NewChildContext return a new ChildContext from the given arguments func NewChildContext(parentContext ParentContext, session view.Session, initiator view.View, errorCallbackFuncs ...func()) *ChildContext { return &ChildContext{Parent: parentContext, session: session, initiator: initiator, errorCallbackFuncs: errorCallbackFuncs} } diff --git a/platform/view/services/view/context.go b/platform/view/services/view/context.go index 29bbf0816..9a35051f2 100644 --- a/platform/view/services/view/context.go +++ b/platform/view/services/view/context.go @@ -63,6 +63,7 @@ type Context struct { localIdentityChecker LocalIdentityChecker } +// NewContextForInitiator returns a new Context for an initiator view func NewContextForInitiator( contextID string, context context.Context, @@ -102,6 +103,7 @@ func NewContextForInitiator( return ctx, nil } +// NewContext returns a new Context func NewContext( context context.Context, sp services.Provider, diff --git a/platform/view/services/view/view.go b/platform/view/services/view/view.go index de6b00a15..00528b994 100644 --- a/platform/view/services/view/view.go +++ b/platform/view/services/view/view.go @@ -16,6 +16,8 @@ import ( "go.opentelemetry.io/otel/trace" ) +// ViewContext is an alias for view.Context +// //go:generate counterfeiter -o mock/context.go -fake-name Context . ViewContext type ViewContext = view.Context diff --git a/platform/view/view/context.go b/platform/view/view/context.go index ac6d6f453..5f37a0d05 100644 --- a/platform/view/view/context.go +++ b/platform/view/view/context.go @@ -59,7 +59,7 @@ func WithViewCall(f func(Context) (interface{}, error)) RunViewOption { } } -// WithSameContext is used to reuse the context +// WithSameContext is used to reuse the view context func WithSameContext() RunViewOption { return func(o *RunViewOptions) error { o.SameContext = true @@ -67,7 +67,8 @@ func WithSameContext() RunViewOption { } } -// WithContext is used to pass a different context to the view +// WithContext is used to pass a different context.Context to the view. +// It includes the effect of WithSameContext as well. func WithContext(ctx context.Context) RunViewOption { return func(o *RunViewOptions) error { o.SameContext = true From 93d5829d615842f4a4761aaa0d7ac7d0f8347d15 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Mon, 24 Nov 2025 13:38:46 +0100 Subject: [PATCH 3/4] refactoring Signed-off-by: Angelo De Caro --- integration/fsc/pingpong/mock/initiator.go | 3 +- .../fsc/pingpong}/mock/runner.go | 0 platform/view/services/view/context.go | 46 +++++++++---------- platform/view/services/view/view.go | 4 +- platform/view/services/view/wrapper.go | 10 ++-- platform/view/view/context.go | 4 +- 6 files changed, 33 insertions(+), 34 deletions(-) rename {platform/view/services/view => integration/fsc/pingpong}/mock/runner.go (100%) diff --git a/integration/fsc/pingpong/mock/initiator.go b/integration/fsc/pingpong/mock/initiator.go index 5ccffc04e..07a0ca3c6 100644 --- a/integration/fsc/pingpong/mock/initiator.go +++ b/integration/fsc/pingpong/mock/initiator.go @@ -12,7 +12,6 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/assert" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/id" - view3 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/view/mock" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" ) @@ -31,7 +30,7 @@ func (p *Initiator) Call(ctx view.Context) (interface{}, error) { responder := identityProvider.Identity("responder") var context view.Context if p.Mock { - c := &view3.DelegatedContext{Ctx: ctx} + c := &DelegatedContext{Ctx: ctx} c.RespondToAs(ctx.Initiator(), responder, &Responder{}) context = c } else { diff --git a/platform/view/services/view/mock/runner.go b/integration/fsc/pingpong/mock/runner.go similarity index 100% rename from platform/view/services/view/mock/runner.go rename to integration/fsc/pingpong/mock/runner.go diff --git a/platform/view/services/view/context.go b/platform/view/services/view/context.go index 9a35051f2..367485505 100644 --- a/platform/view/services/view/context.go +++ b/platform/view/services/view/context.go @@ -44,7 +44,7 @@ type IdentityProvider interface { // Context implements the view.Context interface type Context struct { - context context.Context + ctx context.Context sp services.Provider localSP *ServiceProvider id string @@ -121,7 +121,7 @@ func NewContext( return nil, errors.Errorf("a context should not be nil [%s]", string(debug.Stack())) } ctx := &Context{ - context: context, + ctx: context, id: contextID, resolver: resolver, sessionFactory: sessionFactory, @@ -145,8 +145,8 @@ func NewContext( } func (c *Context) StartSpan(name string, opts ...trace.SpanStartOption) trace.Span { - newCtx, span := c.StartSpanFrom(c.context, name, opts...) - c.context = newCtx + newCtx, span := c.StartSpanFrom(c.ctx, name, opts...) + c.ctx = newCtx return span } @@ -176,7 +176,7 @@ func (c *Context) Identity(ref string) (view.Identity, error) { } func (c *Context) IsMe(id view.Identity) bool { - return c.localIdentityChecker.IsMe(c.context, id) + return c.localIdentityChecker.IsMe(c.ctx, id) } func (c *Context) Caller() view.Identity { @@ -199,7 +199,7 @@ func (c *Context) GetSession(caller view.View, party view.Identity, boundToViews // a session is available, return it if s != nil { - logger.DebugfContext(c.context, "[%s] Reusing session [%s:%s]", c.me, viewId, party) + logger.DebugfContext(c.ctx, "[%s] Reusing session [%s:%s]", c.me, viewId, party) return s, nil } @@ -220,24 +220,24 @@ func (c *Context) GetSessionByID(id string, party view.Identity) (view.Session, var err error s := c.sessions.Get(id, party) if s == nil { - logger.DebugfContext(c.context, "[%s] Creating new session with given id [id:%s][to:%s]", c.me, id, party) + logger.DebugfContext(c.ctx, "[%s] Creating new session with given id [id:%s][to:%s]", c.me, id, party) s, err = c.newSessionByID(id, c.id, party) if err != nil { return nil, err } c.sessions.Put(id, party, s) } else { - logger.DebugfContext(c.context, "[%s] Reusing session with given id [id:%s][to:%s]", id, c.me, party) + logger.DebugfContext(c.ctx, "[%s] Reusing session with given id [id:%s][to:%s]", id, c.me, party) } return s, nil } func (c *Context) Session() view.Session { if c.session == nil { - logger.DebugfContext(c.context, "[%s] No default current Session", c.me) + logger.DebugfContext(c.ctx, "[%s] No default current Session", c.me) return nil } - logger.DebugfContext(c.context, "[%s] Current Session [%s]", c.me, logging.Eval(c.session.Info)) + logger.DebugfContext(c.ctx, "[%s] Current Session [%s]", c.me, logging.Eval(c.session.Info)) return c.session } @@ -267,53 +267,53 @@ func (c *Context) OnError(callback func()) { } func (c *Context) Context() context.Context { - return c.context + return c.ctx } func (c *Context) Dispose() { - logger.DebugfContext(c.context, "Dispose sessions") + logger.DebugfContext(c.ctx, "Dispose sessions") // dispose all sessions c.sessions.Lock() defer c.sessions.Unlock() if c.session != nil { info := c.session.Info() - logger.DebugfContext(c.context, "Delete one session to %s", string(info.Caller)) + logger.DebugfContext(c.ctx, "Delete one session to %s", string(info.Caller)) c.sessionFactory.DeleteSessions(c.Context(), info.ID) } for _, id := range c.sessions.GetSessionIDs() { - logger.DebugfContext(c.context, "Delete session %s", id) + logger.DebugfContext(c.ctx, "Delete session %s", id) c.sessionFactory.DeleteSessions(c.Context(), id) } c.sessions.Reset() } func (c *Context) newSession(view view.View, contextID string, party view.Identity) (view.Session, error) { - resolver, pkid, err := c.resolver.Resolver(c.context, party) + resolver, pkid, err := c.resolver.Resolver(c.ctx, party) if err != nil { return nil, err } - logger.DebugfContext(c.context, "Open new session to %s", resolver.GetName()) + logger.DebugfContext(c.ctx, "Open new session to %s", resolver.GetName()) return c.sessionFactory.NewSession(GetIdentifier(view), contextID, resolver.GetAddress(endpoint.P2PPort), pkid) } func (c *Context) newSessionByID(sessionID, contextID string, party view.Identity) (view.Session, error) { - resolver, pkid, err := c.resolver.Resolver(c.context, party) + resolver, pkid, err := c.resolver.Resolver(c.ctx, party) if err != nil { return nil, err } var ep string if resolver != nil { ep = resolver.GetAddress(endpoint.P2PPort) - logger.DebugfContext(c.context, "Open new session by id to %s", resolver.GetName()) + logger.DebugfContext(c.ctx, "Open new session by id to %s", resolver.GetName()) } - logger.DebugfContext(c.context, "Open new session by id to %s", ep) + logger.DebugfContext(c.ctx, "Open new session by id to %s", ep) return c.sessionFactory.NewSessionWithID(sessionID, contextID, ep, pkid, nil, nil) } func (c *Context) Cleanup() { - logger.DebugfContext(c.context, "cleaning up context [%s][%d]", c.ID(), len(c.errorCallbackFuncs)) + logger.DebugfContext(c.ctx, "cleaning up context [%s][%d]", c.ID(), len(c.errorCallbackFuncs)) for _, callbackFunc := range c.errorCallbackFuncs { c.safeInvoke(callbackFunc) } @@ -322,7 +322,7 @@ func (c *Context) Cleanup() { func (c *Context) safeInvoke(f func()) { defer func() { if r := recover(); r != nil { - logger.DebugfContext(c.context, "function [%s] panicked [%s]", f, r) + logger.DebugfContext(c.ctx, "function [%s] panicked [%s]", f, r) } }() f() @@ -332,7 +332,7 @@ func (c *Context) resolve(id view.Identity) (view.Identity, error) { if id.IsNone() { return nil, errors.New("no id provided") } - resolver, _, err := c.resolver.Resolver(c.context, id) + resolver, _, err := c.resolver.Resolver(c.ctx, id) if err != nil { return nil, err } @@ -340,7 +340,7 @@ func (c *Context) resolve(id view.Identity) (view.Identity, error) { } func (c *Context) createSession(caller view.View, party view.Identity, aliases ...view.View) (view.Session, error) { - logger.DebugfContext(c.context, "create session [%s][%s], [%s:%s]", c.me, c.id, getViewIdentifier(caller), party) + logger.DebugfContext(c.ctx, "create session [%s][%s], [%s:%s]", c.me, c.id, getViewIdentifier(caller), party) s, err := c.newSession(caller, c.id, party) if err != nil { diff --git a/platform/view/services/view/view.go b/platform/view/services/view/view.go index 00528b994..efce82ae8 100644 --- a/platform/view/services/view/view.go +++ b/platform/view/services/view/view.go @@ -90,8 +90,8 @@ func RunViewNow(ctx ParentContext, v View, opts ...view.RunViewOption) (res inte } goContext := ctx.Context() - if options.Context != nil { - goContext = options.Context + if options.Ctx != nil { + goContext = options.Ctx } logger.DebugfContext(goContext, "Start view %s", GetName(v)) diff --git a/platform/view/services/view/wrapper.go b/platform/view/services/view/wrapper.go index 4bc78a540..374e8246e 100644 --- a/platform/view/services/view/wrapper.go +++ b/platform/view/services/view/wrapper.go @@ -13,18 +13,18 @@ import ( // WrappedContext wraps an existing view context to provider a different context.Context type WrappedContext struct { ParentContext - goContext context.Context + ctx context.Context } // WrapContext returns a new WrappedContext for the given arguments -func WrapContext(ctx ParentContext, goContext context.Context) *WrappedContext { +func WrapContext(parent ParentContext, ctx context.Context) *WrappedContext { return &WrappedContext{ - ParentContext: ctx, - goContext: goContext, + ParentContext: parent, + ctx: ctx, } } // Context returns the overrode go context func (c *WrappedContext) Context() context.Context { - return c.goContext + return c.ctx } diff --git a/platform/view/view/context.go b/platform/view/view/context.go index 5f37a0d05..9cf8e48a5 100644 --- a/platform/view/view/context.go +++ b/platform/view/view/context.go @@ -18,7 +18,7 @@ type RunViewOptions struct { AsInitiator bool Call func(Context) (interface{}, error) SameContext bool - Context context.Context + Ctx context.Context } // CompileRunViewOptions compiles a set of RunViewOption to a RunViewOptions @@ -72,7 +72,7 @@ func WithSameContext() RunViewOption { func WithContext(ctx context.Context) RunViewOption { return func(o *RunViewOptions) error { o.SameContext = true - o.Context = ctx + o.Ctx = ctx return nil } } From a53402e544daf6d91adf892c3649bf5e01902bb4 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Tue, 25 Nov 2025 08:06:34 +0100 Subject: [PATCH 4/4] name refactoring Signed-off-by: Angelo De Caro --- platform/view/services/view/view.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/view/services/view/view.go b/platform/view/services/view/view.go index efce82ae8..475c25dc3 100644 --- a/platform/view/services/view/view.go +++ b/platform/view/services/view/view.go @@ -79,7 +79,7 @@ func AsInitiatorView(context view.Context, initiator View) (interface{}, error) // RunViewNow invokes the Call function of the given view. // The view context used to the run view is either ctx or the one extracted from the options (see view.WithContext), if present. -func RunViewNow(ctx ParentContext, v View, opts ...view.RunViewOption) (res interface{}, err error) { +func RunViewNow(parent ParentContext, v View, opts ...view.RunViewOption) (res interface{}, err error) { options, err := view.CompileRunViewOptions(opts...) if err != nil { return nil, errors.Wrap(err, "failed compiling options") @@ -89,13 +89,13 @@ func RunViewNow(ctx ParentContext, v View, opts ...view.RunViewOption) (res inte initiator = v } - goContext := ctx.Context() + goContext := parent.Context() if options.Ctx != nil { goContext = options.Ctx } logger.DebugfContext(goContext, "Start view %s", GetName(v)) - newCtx, span := ctx.StartSpanFrom(goContext, GetName(v), tracing.WithAttributes( + newCtx, span := parent.StartSpanFrom(goContext, GetName(v), tracing.WithAttributes( tracing.String(ViewLabel, GetIdentifier(v)), tracing.String(InitiatorViewLabel, GetIdentifier(initiator)), ), trace.WithSpanKind(trace.SpanKindInternal)) @@ -103,12 +103,12 @@ func RunViewNow(ctx ParentContext, v View, opts ...view.RunViewOption) (res inte var cc ParentContext if options.SameContext { - cc = WrapContext(ctx, newCtx) + cc = WrapContext(parent, newCtx) } else { if options.AsInitiator { - cc = NewChildContextFromParentAndInitiator(WrapContext(ctx, newCtx), initiator) + cc = NewChildContextFromParentAndInitiator(WrapContext(parent, newCtx), initiator) // register options.Session under initiator - contextSession := ctx.Session() + contextSession := parent.Session() if contextSession == nil { return nil, errors.Errorf("cannot convert a non-responder context to an initiator context") } @@ -116,7 +116,7 @@ func RunViewNow(ctx ParentContext, v View, opts ...view.RunViewOption) (res inte return nil, errors.Wrapf(err, "failed registering default session as initiated by [%s:%s]", initiator, contextSession.Info().Caller) } } else { - cc = NewChildContext(WrapContext(ctx, newCtx), options.Session, initiator) + cc = NewChildContext(WrapContext(parent, newCtx), options.Session, initiator) } }