Skip to content
This repository has been archived by the owner on May 1, 2020. It is now read-only.

Commit

Permalink
Implement dedicated sessions disabled error type
Browse files Browse the repository at this point in the history
Implement dedicated error and message types for the case
of disabled sessions.
Add a new integration test case to verify the correct error type
returned by session related methods of both the client
and the client agent.
  • Loading branch information
romshark committed Mar 19, 2018
1 parent 5c8eb2d commit 060c85b
Show file tree
Hide file tree
Showing 19 changed files with 120 additions and 19 deletions.
4 changes: 2 additions & 2 deletions client.go
Expand Up @@ -65,7 +65,7 @@ func (clt *Client) Signal(name string, payload Payload) error {
// Returns an error if there's already another session active
func (clt *Client) CreateSession(attachment interface{}) error {
if !clt.srv.sessionsEnabled {
return fmt.Errorf("Sessions disabled")
return SessionsDisabled{}
}

clt.lock.Lock()
Expand Down Expand Up @@ -131,7 +131,7 @@ func (clt *Client) notifySessionClosed() error {
// Does nothing if there's no active session
func (clt *Client) CloseSession() error {
if !clt.srv.sessionsEnabled {
return fmt.Errorf("Sessions disabled")
return SessionsDisabled{}
}
if clt.Session == nil {
return nil
Expand Down
2 changes: 1 addition & 1 deletion client/client.go
Expand Up @@ -302,7 +302,7 @@ func (clt *Client) CloseSession() error {
webwire.Payload{},
clt.defaultTimeout,
); err != nil {
return fmt.Errorf("Session destruction request failed: %s", err)
return err
}
}

Expand Down
6 changes: 6 additions & 0 deletions client/handle.go
Expand Up @@ -58,6 +58,10 @@ func (clt *Client) handleMaxSessConnsReached(reqIdent [8]byte) {
clt.requestManager.Fail(reqIdent, webwire.MaxSessConnsReached{})
}

func (clt *Client) handleSessionsDisabled(reqIdent [8]byte) {
clt.requestManager.Fail(reqIdent, webwire.SessionsDisabled{})
}

func (clt *Client) handleReply(reqID [8]byte, payload webwire.Payload) {
clt.requestManager.Fulfill(reqID, payload)
}
Expand Down Expand Up @@ -97,6 +101,8 @@ func (clt *Client) handleMessage(message []byte) error {
clt.handleSessionNotFound(extractMessageIdentifier(message))
case webwire.MsgMaxSessConnsReached:
clt.handleMaxSessConnsReached(extractMessageIdentifier(message))
case webwire.MsgSessionsDisabled:
clt.handleSessionsDisabled(extractMessageIdentifier(message))
case webwire.MsgErrorReply:
clt.handleFailure(extractMessageIdentifier(message), message[9:])
case webwire.MsgReplyInternalError:
Expand Down
7 changes: 7 additions & 0 deletions errors.go
Expand Up @@ -99,6 +99,13 @@ func (err ReqErr) Error() string {
return err.Message
}

// SessionsDisabled represents an error type indicating that the server has sessions disabled
type SessionsDisabled struct{}

func (err SessionsDisabled) Error() string {
return "Sessions are disabled for this server"
}

// SessNotFound represents a session restoration error type indicating that the server didn't
// find the session to be restored
type SessNotFound struct{}
Expand Down
6 changes: 6 additions & 0 deletions message.go
Expand Up @@ -71,6 +71,10 @@ const (
// when the maximum number of concurrent connections for a certain session was reached
MsgMaxSessConnsReached = byte(4)

// MsgSessionsDisabled is sent by the server in response to a session restoration request
// if sessions are disabled for the target server
MsgSessionsDisabled = byte(5)

// MsgSessionCreated is sent by the server
// to notify the client about the session creation
MsgSessionCreated = byte(21)
Expand Down Expand Up @@ -786,6 +790,8 @@ func (msg *Message) createFailCallback(client *Client, srv *Server) {
msgType = MsgMaxSessConnsReached
case SessNotFound:
msgType = MsgSessionNotFound
case SessionsDisabled:
msgType = MsgSessionsDisabled
default:
msgType = MsgReplyInternalError
}
Expand Down
30 changes: 14 additions & 16 deletions server.go
Expand Up @@ -104,6 +104,7 @@ func (hooks *Hooks) SetDefaults() {
// ServerOptions represents the options used during the creation of a new WebWire server instance
type ServerOptions struct {
Hooks Hooks
SessionsEnabled bool
MaxSessionConnections uint
WarnLog io.Writer
ErrorLog io.Writer
Expand Down Expand Up @@ -147,11 +148,16 @@ type Server struct {
func NewServer(opts ServerOptions) *Server {
opts.SetDefaults()

sessionsEnabled := false
if opts.Hooks.OnSessionCreated != nil &&
opts.Hooks.OnSessionLookup != nil &&
opts.Hooks.OnSessionClosed != nil {
sessionsEnabled = true
if opts.SessionsEnabled {
if opts.Hooks.OnSessionCreated == nil {
panic("Expected OnSessionCreated hook to be defined because sessions are enabled")
}
if opts.Hooks.OnSessionLookup == nil {
panic("Expected OnSessionLookup hook to be defined because sessions are enabled")
}
if opts.Hooks.OnSessionClosed == nil {
panic("Expected OnSessionClosed hook to be defined because sessions are enabled")
}
}

srv := Server{
Expand All @@ -164,7 +170,7 @@ func NewServer(opts ServerOptions) *Server {
opsLock: sync.Mutex{},
clients: make([]*Client, 0),
clientsLock: &sync.Mutex{},
sessionsEnabled: sessionsEnabled,
sessionsEnabled: opts.SessionsEnabled,
SessionRegistry: newSessionRegistry(opts.MaxSessionConnections),

// Internals
Expand Down Expand Up @@ -194,11 +200,7 @@ func NewServer(opts ServerOptions) *Server {
// and returns an error if the ongoing connection cannot be proceeded
func (srv *Server) handleSessionRestore(msg *Message) error {
if !srv.sessionsEnabled {
// TODO: Implement dedicated error message type for "sessions disabled" errors
msg.fail(ReqErr{
Code: "SESSIONS_DISABLED",
Message: "Sessions are disabled on this server instance",
})
msg.fail(SessionsDisabled{})
return nil
}

Expand Down Expand Up @@ -244,11 +246,7 @@ func (srv *Server) handleSessionRestore(msg *Message) error {
// and returns an error if the ongoing connection cannot be proceeded
func (srv *Server) handleSessionClosure(msg *Message) error {
if !srv.sessionsEnabled {
// TODO: Implement dedicated error message type for "max connection reached" errors
msg.fail(ReqErr{
Code: "SESSIONS_DISABLED",
Message: "Sessions are disabled on this server instance",
})
msg.fail(SessionsDisabled{})
return nil
}

Expand Down
1 change: 1 addition & 0 deletions test/activeSessionRegistry_test.go
Expand Up @@ -15,6 +15,7 @@ func TestActiveSessionRegistry(t *testing.T) {
srv, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
1 change: 1 addition & 0 deletions test/authentication_test.go
Expand Up @@ -64,6 +64,7 @@ func TestAuthentication(t *testing.T) {
_, addr := setupServer(
t,
wwr.ServerOptions{
SessionsEnabled: true,
Hooks: wwr.Hooks{
OnSignal: func(ctx context.Context) {
defer clientSignalReceived.Done()
Expand Down
1 change: 1 addition & 0 deletions test/clientAutomaticSessionRestoration_test.go
Expand Up @@ -21,6 +21,7 @@ func TestClientAutomaticSessionRestoration(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
1 change: 1 addition & 0 deletions test/clientInitiatedSessionDestruction_test.go
Expand Up @@ -29,6 +29,7 @@ func TestClientInitiatedSessionDestruction(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
1 change: 1 addition & 0 deletions test/clientOfflineSessionClosure_test.go
Expand Up @@ -21,6 +21,7 @@ func TestClientOfflineSessionClosure(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
1 change: 1 addition & 0 deletions test/clientOnSessionClosed_test.go
Expand Up @@ -18,6 +18,7 @@ func TestClientOnSessionClosed(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
1 change: 1 addition & 0 deletions test/clientOnSessionCreated_test.go
Expand Up @@ -19,6 +19,7 @@ func TestClientOnSessionCreated(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
1 change: 1 addition & 0 deletions test/clientSessionInfo_test.go
Expand Up @@ -27,6 +27,7 @@ func TestClientSessionInfo(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
1 change: 1 addition & 0 deletions test/clientSessionRestoration_test.go
Expand Up @@ -21,6 +21,7 @@ func TestClientSessionRestoration(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down
72 changes: 72 additions & 0 deletions test/disabledSessions_test.go
@@ -0,0 +1,72 @@
package test

import (
"context"
"reflect"
"testing"
"time"

wwr "github.com/qbeon/webwire-go"
wwrclt "github.com/qbeon/webwire-go/client"
)

// TestDisabledSessions verifies the server is connectable,
// and is able to receives requests and signals, create sessions
// and identify clients during request- and signal handling
func TestDisabledSessions(t *testing.T) {
verifyError := func(err error) {
if _, isDisabledErr := err.(wwr.SessionsDisabled); !isDisabledErr {
t.Errorf(
"Expected SessionsDisabled error, got: %s | %s",
reflect.TypeOf(err),
err,
)
}
}

// Initialize webwire server
_, addr := setupServer(
t,
wwr.ServerOptions{
SessionsEnabled: false,
Hooks: wwr.Hooks{
OnRequest: func(ctx context.Context) (wwr.Payload, error) {
// Extract request message and requesting client from the context
msg := ctx.Value(wwr.Msg).(wwr.Message)

// Try to create a new session and expect an error
createErr := msg.Client.CreateSession(nil)
verifyError(createErr)

// Try to create a new session and expect an error
closeErr := msg.Client.CloseSession()
verifyError(closeErr)

return wwr.Payload{}, nil
},
},
},
)

// Initialize client
client := wwrclt.NewClient(
addr,
wwrclt.Options{
DefaultRequestTimeout: 2 * time.Second,
},
)
defer client.Close()

if err := client.Connect(); err != nil {
t.Fatalf("Couldn't connect: %s", err)
}

// Send authentication request and await reply
_, err := client.Request("login", wwr.Payload{Data: []byte("testdata")})
if err != nil {
t.Fatalf("Request failed: %s", err)
}

sessRestErr := client.RestoreSession([]byte("testkey"))
verifyError(sessRestErr)
}
1 change: 1 addition & 0 deletions test/maxConcSessConn_test.go
Expand Up @@ -22,6 +22,7 @@ func TestMaxConcSessConn(t *testing.T) {
_, addr := setupServer(
t,
wwr.ServerOptions{
SessionsEnabled: true,
MaxSessionConnections: concurrentConns,
Hooks: wwr.Hooks{
OnClientConnected: func(client *wwr.Client) {
Expand Down
1 change: 1 addition & 0 deletions test/restoreInexistentSession_test.go
Expand Up @@ -15,6 +15,7 @@ func TestRestoreInexistentSession(t *testing.T) {
_, addr := setupServer(
t,
wwr.ServerOptions{
SessionsEnabled: true,
Hooks: wwr.Hooks{
// Permanently store the session
OnSessionCreated: func(_ *wwr.Client) error {
Expand Down
1 change: 1 addition & 0 deletions test/serverInitiatedSessionDestruction_test.go
Expand Up @@ -28,6 +28,7 @@ func TestServerInitiatedSessionDestruction(t *testing.T) {
_, addr := setupServer(
t,
webwire.ServerOptions{
SessionsEnabled: true,
Hooks: webwire.Hooks{
OnRequest: func(ctx context.Context) (webwire.Payload, error) {
// Extract request message and requesting client from the context
Expand Down

0 comments on commit 060c85b

Please sign in to comment.