feat: Add custom summary error type (#3459)
Add custom error type to to decode and encode `Errors` field Added some extra checks to handle existing BSR summary types with `Error` fields
This commit is contained in:
1 parent
39e6fcfeba
commit
6afd2c96a5
2 files changed
+151
-6
No files matched your search
+45
-6
@@ -5,10 +5,49 @@ package bsr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SummaryError struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e *SummaryError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func (e *SummaryError) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(e.Message)
|
||||
}
|
||||
|
||||
func (e *SummaryError) UnmarshalJSON(data []byte) error {
|
||||
var rawMessage json.RawMessage
|
||||
var message string
|
||||
|
||||
err := json.Unmarshal(data, &rawMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case len(rawMessage) > 0 && string(rawMessage) == `"{}"`:
|
||||
e.Message = ""
|
||||
case len(rawMessage) > 0 && string(rawMessage) == `"null"`:
|
||||
e.Message = ""
|
||||
case len(rawMessage) <= 0:
|
||||
e.Message = ""
|
||||
default:
|
||||
if err := json.Unmarshal(data, &message); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Message = message
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BaseSummary contains the common fields of all summary types.
|
||||
type BaseSummary struct {
|
||||
Id string
|
||||
@@ -49,7 +88,7 @@ type BaseSessionSummary struct {
|
||||
ConnectionCount uint64
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
Errors string
|
||||
Errors SummaryError
|
||||
}
|
||||
|
||||
// SessionSummary contains statistics for a session container
|
||||
@@ -89,12 +128,12 @@ func (b *BaseSessionSummary) GetConnectionCount() uint64 {
|
||||
|
||||
// GetErrors returns errors.
|
||||
func (b *BaseSessionSummary) GetErrors() error {
|
||||
return errors.New(b.Errors)
|
||||
return errors.New(b.Errors.Message)
|
||||
}
|
||||
|
||||
// SetErrors sets errors.
|
||||
func (b *BaseSessionSummary) SetErrors(e error) {
|
||||
b.Errors = e.Error()
|
||||
b.Errors = SummaryError{Message: e.Error()}
|
||||
}
|
||||
|
||||
// BaseChannelSummary encapsulates data for a channel, including its id, channel type,
|
||||
@@ -170,7 +209,7 @@ type BaseConnectionSummary struct {
|
||||
EndTime time.Time
|
||||
BytesUp uint64
|
||||
BytesDown uint64
|
||||
Errors string
|
||||
Errors SummaryError
|
||||
}
|
||||
|
||||
// ConnectionSummary contains statistics for a connection container
|
||||
@@ -224,10 +263,10 @@ func (b *BaseConnectionSummary) GetBytesDown() uint64 {
|
||||
|
||||
// GetErrors returns errors.
|
||||
func (b *BaseConnectionSummary) GetErrors() error {
|
||||
return errors.New(b.Errors)
|
||||
return &b.Errors
|
||||
}
|
||||
|
||||
// SetErrors sets errors.
|
||||
func (b *BaseConnectionSummary) SetErrors(e error) {
|
||||
b.Errors = e.Error()
|
||||
b.Errors = SummaryError{Message: e.Error()}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package bsr_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/bsr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSummaryError_MarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
in string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "error string",
|
||||
in: "error",
|
||||
want: "\"error\"",
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
in: "",
|
||||
want: "\"\"",
|
||||
},
|
||||
{
|
||||
name: "empty object",
|
||||
in: `{}`,
|
||||
want: "\"{}\"",
|
||||
},
|
||||
{
|
||||
name: "empty object",
|
||||
in: `null`,
|
||||
want: "\"null\"",
|
||||
},
|
||||
{
|
||||
name: "key value object",
|
||||
in: `{"message": "failed to load"}`,
|
||||
want: "\"{\\\"message\\\": \\\"failed to load\\\"}\"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
summaryErr := bsr.SummaryError{Message: tc.in}
|
||||
|
||||
got, err := summaryErr.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.want, string(got))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSummaryError_UnmarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
in any
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "error string",
|
||||
in: "error",
|
||||
want: "error",
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
in: "",
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "empty object",
|
||||
in: `{}`,
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "empty object",
|
||||
in: `null`,
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "key value object",
|
||||
in: `{"message": "failed to load"}`,
|
||||
want: "{\"message\": \"failed to load\"}",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var summaryErr bsr.SummaryError
|
||||
|
||||
input, err := json.Marshal(tc.in)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = summaryErr.UnmarshalJSON(input)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.want, summaryErr.Message)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user