better parsing of graph odata errs (#4900)
parse the odataerr to a local struct that has a more complete view of the data. --- #### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🧹 Tech Debt/Cleanup #### Issue(s) * #4685 #### Test Plan - [x] ⚡ Unit test - [x] 💚 E2E
This commit is contained in:
parent
c65527e5c4
commit
8c0ac505a2
@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
|
||||
@ -141,15 +142,15 @@ var (
|
||||
|
||||
func IsErrApplicationThrottled(err error) bool {
|
||||
return errors.Is(err, ErrApplicationThrottled) ||
|
||||
hasErrorCode(err, applicationThrottled)
|
||||
parseODataErr(err).hasErrorCode(err, applicationThrottled)
|
||||
}
|
||||
|
||||
func IsErrAuthenticationError(err error) bool {
|
||||
return hasErrorCode(err, AuthenticationError)
|
||||
return parseODataErr(err).hasErrorCode(err, AuthenticationError)
|
||||
}
|
||||
|
||||
func IsErrInsufficientAuthorization(err error) bool {
|
||||
return hasErrorCode(err, AuthorizationRequestDenied)
|
||||
return parseODataErr(err).hasErrorCode(err, AuthorizationRequestDenied)
|
||||
}
|
||||
|
||||
func IsErrDeletedInFlight(err error) bool {
|
||||
@ -157,7 +158,7 @@ func IsErrDeletedInFlight(err error) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if hasErrorCode(
|
||||
if parseODataErr(err).hasErrorCode(
|
||||
err,
|
||||
errorItemNotFound,
|
||||
itemNotFound,
|
||||
@ -169,56 +170,51 @@ func IsErrDeletedInFlight(err error) bool {
|
||||
}
|
||||
|
||||
func IsErrItemNotFound(err error) bool {
|
||||
return hasErrorCode(err, itemNotFound, errorItemNotFound)
|
||||
return parseODataErr(err).hasErrorCode(err, itemNotFound, errorItemNotFound)
|
||||
}
|
||||
|
||||
func IsErrInvalidDelta(err error) bool {
|
||||
return hasErrorCode(err, syncStateNotFound, resyncRequired, syncStateInvalid)
|
||||
return parseODataErr(err).hasErrorCode(err, syncStateNotFound, resyncRequired, syncStateInvalid)
|
||||
}
|
||||
|
||||
func IsErrDeltaNotSupported(err error) bool {
|
||||
return hasErrorMessage(err, ParameterDeltaTokenNotSupported)
|
||||
return parseODataErr(err).hasErrorMessage(err, ParameterDeltaTokenNotSupported)
|
||||
}
|
||||
|
||||
func IsErrQuotaExceeded(err error) bool {
|
||||
return hasErrorCode(err, QuotaExceeded)
|
||||
return parseODataErr(err).hasErrorCode(err, QuotaExceeded)
|
||||
}
|
||||
|
||||
func IsErrExchangeMailFolderNotFound(err error) bool {
|
||||
// Not sure if we can actually see a resourceNotFound error here. I've only
|
||||
// seen the latter two.
|
||||
return hasErrorCode(err, ResourceNotFound, errorItemNotFound, MailboxNotEnabledForRESTAPI)
|
||||
return parseODataErr(err).hasErrorCode(err, ResourceNotFound, errorItemNotFound, MailboxNotEnabledForRESTAPI)
|
||||
}
|
||||
|
||||
func IsErrUserNotFound(err error) bool {
|
||||
if hasErrorCode(err, RequestResourceNotFound, invalidUser) {
|
||||
ode := parseODataErr(err)
|
||||
|
||||
if ode.hasErrorCode(err, RequestResourceNotFound, invalidUser) {
|
||||
return true
|
||||
}
|
||||
|
||||
if hasErrorCode(err, ResourceNotFound) {
|
||||
var odErr odataerrors.ODataErrorable
|
||||
if !errors.As(err, &odErr) {
|
||||
return false
|
||||
}
|
||||
|
||||
mainMsg, _, _ := errData(odErr)
|
||||
|
||||
return strings.Contains(strings.ToLower(mainMsg), "user")
|
||||
if ode.hasErrorCode(err, ResourceNotFound) {
|
||||
return strings.Contains(strings.ToLower(ode.Main.Message), "user")
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsErrInvalidRecipients(err error) bool {
|
||||
return hasErrorCode(err, ErrorInvalidRecipients)
|
||||
return parseODataErr(err).hasErrorCode(err, ErrorInvalidRecipients)
|
||||
}
|
||||
|
||||
func IsErrCannotOpenFileAttachment(err error) bool {
|
||||
return hasErrorCode(err, cannotOpenFileAttachment)
|
||||
return parseODataErr(err).hasErrorCode(err, cannotOpenFileAttachment)
|
||||
}
|
||||
|
||||
func IsErrAccessDenied(err error) bool {
|
||||
return hasErrorCode(err, ErrorAccessDenied) ||
|
||||
return parseODataErr(err).hasErrorCode(err, ErrorAccessDenied) ||
|
||||
clues.HasLabel(err, LabelStatus(http.StatusForbidden))
|
||||
}
|
||||
|
||||
@ -240,17 +236,17 @@ func IsErrConnectionReset(err error) bool {
|
||||
|
||||
func IsErrUnauthorizedOrBadToken(err error) bool {
|
||||
return clues.HasLabel(err, LabelStatus(http.StatusUnauthorized)) ||
|
||||
hasErrorCode(err, invalidAuthenticationToken) ||
|
||||
parseODataErr(err).hasErrorCode(err, invalidAuthenticationToken) ||
|
||||
errors.Is(err, ErrTokenExpired)
|
||||
}
|
||||
|
||||
func IsErrBadJWTToken(err error) bool {
|
||||
return hasErrorCode(err, invalidAuthenticationToken)
|
||||
return parseODataErr(err).hasErrorCode(err, invalidAuthenticationToken)
|
||||
}
|
||||
|
||||
func IsErrItemAlreadyExistsConflict(err error) bool {
|
||||
return errors.Is(err, ErrItemAlreadyExistsConflict) ||
|
||||
hasErrorCode(err, nameAlreadyExists)
|
||||
parseODataErr(err).hasErrorCode(err, nameAlreadyExists)
|
||||
}
|
||||
|
||||
// LabelStatus transforms the provided statusCode into
|
||||
@ -262,7 +258,7 @@ func LabelStatus(statusCode int) string {
|
||||
|
||||
// IsMalware is true if the graphAPI returns a "malware detected" error code.
|
||||
func IsMalware(err error) bool {
|
||||
return hasErrorCode(err, malwareDetected)
|
||||
return parseODataErr(err).hasErrorCode(err, malwareDetected)
|
||||
}
|
||||
|
||||
func IsMalwareResp(ctx context.Context, resp *http.Response) bool {
|
||||
@ -274,22 +270,26 @@ func IsMalwareResp(ctx context.Context, resp *http.Response) bool {
|
||||
}
|
||||
|
||||
func IsErrFolderExists(err error) bool {
|
||||
return hasErrorCode(err, folderExists)
|
||||
return parseODataErr(err).hasErrorCode(err, folderExists)
|
||||
}
|
||||
|
||||
func IsErrUsersCannotBeResolved(err error) bool {
|
||||
return hasErrorCode(err, noResolvedUsers) || hasErrorMessage(err, usersCannotBeResolved)
|
||||
ode := parseODataErr(err)
|
||||
|
||||
return ode.hasErrorCode(err, noResolvedUsers) || ode.hasErrorMessage(err, usersCannotBeResolved)
|
||||
}
|
||||
|
||||
func IsErrSiteNotFound(err error) bool {
|
||||
return hasErrorMessage(err, requestedSiteCouldNotBeFound)
|
||||
return parseODataErr(err).hasErrorMessage(err, requestedSiteCouldNotBeFound)
|
||||
}
|
||||
|
||||
func IsErrResourceLocked(err error) bool {
|
||||
ode := parseODataErr(err)
|
||||
|
||||
return errors.Is(err, ErrResourceLocked) ||
|
||||
hasInnerErrorCode(err, ResourceLocked) ||
|
||||
hasErrorCode(err, NotAllowed) ||
|
||||
errMessageMatchesAllFilters(
|
||||
ode.hasInnerErrorCode(err, ResourceLocked) ||
|
||||
ode.hasErrorCode(err, NotAllowed) ||
|
||||
ode.errMessageMatchesAllFilters(
|
||||
err,
|
||||
filters.In([]string{"the service principal for resource"}),
|
||||
filters.In([]string{"this indicate that a subscription within the tenant has lapsed"}),
|
||||
@ -297,105 +297,7 @@ func IsErrResourceLocked(err error) bool {
|
||||
}
|
||||
|
||||
func IsErrSharingDisabled(err error) bool {
|
||||
return hasInnerErrorCode(err, sharingDisabled)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// error parsers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func hasErrorCode(err error, codes ...errorCode) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var oDataError odataerrors.ODataErrorable
|
||||
if !errors.As(err, &oDataError) {
|
||||
return false
|
||||
}
|
||||
|
||||
code, ok := ptr.ValOK(oDataError.GetErrorEscaped().GetCode())
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
cs := make([]string, len(codes))
|
||||
for i, c := range codes {
|
||||
cs[i] = string(c)
|
||||
}
|
||||
|
||||
return filters.Equal(cs).Compare(code)
|
||||
}
|
||||
|
||||
func hasInnerErrorCode(err error, codes ...errorCode) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var oDataError odataerrors.ODataErrorable
|
||||
if !errors.As(err, &oDataError) {
|
||||
return false
|
||||
}
|
||||
|
||||
inner := oDataError.GetErrorEscaped().GetInnerError()
|
||||
if inner == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
code, err := str.AnyValueToString("code", inner.GetAdditionalData())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
cs := make([]string, len(codes))
|
||||
for i, c := range codes {
|
||||
cs[i] = string(c)
|
||||
}
|
||||
|
||||
return filters.Equal(cs).Compare(code)
|
||||
}
|
||||
|
||||
// only use this as a last resort. Prefer the code or statuscode if possible.
|
||||
func hasErrorMessage(err error, msgs ...errorMessage) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var oDataError odataerrors.ODataErrorable
|
||||
if !errors.As(err, &oDataError) {
|
||||
return false
|
||||
}
|
||||
|
||||
msg, ok := ptr.ValOK(oDataError.GetErrorEscaped().GetMessage())
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
cs := make([]string, len(msgs))
|
||||
for i, c := range msgs {
|
||||
cs[i] = string(c)
|
||||
}
|
||||
|
||||
return filters.In(cs).Compare(msg)
|
||||
}
|
||||
|
||||
// only use this as a last resort. Prefer the code or statuscode if possible.
|
||||
func errMessageMatchesAllFilters(err error, fs ...filters.Filter) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var oDataError odataerrors.ODataErrorable
|
||||
if !errors.As(err, &oDataError) {
|
||||
return false
|
||||
}
|
||||
|
||||
msg, ok := ptr.ValOK(oDataError.GetErrorEscaped().GetMessage())
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return filters.Must(msg, fs...)
|
||||
return parseODataErr(err).hasInnerErrorCode(err, sharingDisabled)
|
||||
}
|
||||
|
||||
// Wrap is a helper function that extracts ODataError metadata from
|
||||
@ -405,20 +307,20 @@ func Wrap(ctx context.Context, e error, msg string) *clues.Err {
|
||||
return nil
|
||||
}
|
||||
|
||||
var oDataError odataerrors.ODataErrorable
|
||||
if !errors.As(e, &oDataError) {
|
||||
return clues.WrapWC(ctx, e, msg).WithTrace(1)
|
||||
ode := parseODataErr(e)
|
||||
if !ode.isODataErr {
|
||||
return clues.StackWC(ctx, e).WithTrace(1)
|
||||
}
|
||||
|
||||
mainMsg, data, innerMsg := errData(oDataError)
|
||||
|
||||
if len(mainMsg) > 0 {
|
||||
e = clues.Stack(e, clues.New(mainMsg))
|
||||
if len(ode.Main.Message) > 0 {
|
||||
e = clues.Stack(e, clues.New(ode.Main.Message))
|
||||
}
|
||||
|
||||
ce := clues.WrapWC(ctx, e, msg).With(data...).WithTrace(1)
|
||||
ce := clues.WrapWC(ctx, e, msg).
|
||||
With("graph_api_err", ode).
|
||||
WithTrace(1)
|
||||
|
||||
return setLabels(ce, innerMsg)
|
||||
return setLabels(ce, ode)
|
||||
}
|
||||
|
||||
// Stack is a helper function that extracts ODataError metadata from
|
||||
@ -428,20 +330,20 @@ func Stack(ctx context.Context, e error) *clues.Err {
|
||||
return nil
|
||||
}
|
||||
|
||||
var oDataError *odataerrors.ODataError
|
||||
if !errors.As(e, &oDataError) {
|
||||
ode := parseODataErr(e)
|
||||
if !ode.isODataErr {
|
||||
return clues.StackWC(ctx, e).WithTrace(1)
|
||||
}
|
||||
|
||||
mainMsg, data, innerMsg := errData(oDataError)
|
||||
|
||||
if len(mainMsg) > 0 {
|
||||
e = clues.Stack(e, clues.New(mainMsg))
|
||||
if len(ode.Main.Message) > 0 {
|
||||
e = clues.Stack(e, clues.New(ode.Main.Message))
|
||||
}
|
||||
|
||||
ce := clues.StackWC(ctx, e).With(data...).WithTrace(1)
|
||||
ce := clues.StackWC(ctx, e).
|
||||
With("graph_api_err", ode).
|
||||
WithTrace(1)
|
||||
|
||||
return setLabels(ce, innerMsg)
|
||||
return setLabels(ce, ode)
|
||||
}
|
||||
|
||||
// stackReq is a helper function that extracts ODataError metadata from
|
||||
@ -467,12 +369,12 @@ func stackReq(
|
||||
// Checks for the following conditions and labels the error accordingly:
|
||||
// * mysiteNotFound | mysiteURLNotFound
|
||||
// * malware
|
||||
func setLabels(err *clues.Err, msg string) *clues.Err {
|
||||
func setLabels(err *clues.Err, ode oDataErr) *clues.Err {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
f := filters.Contains([]string{msg})
|
||||
f := filters.Contains([]string{ode.Main.Message + ode.Main.Code})
|
||||
|
||||
if f.Compare(string(MysiteNotFound)) ||
|
||||
f.Compare(string(MysiteURLNotFound)) {
|
||||
@ -490,35 +392,6 @@ func setLabels(err *clues.Err, msg string) *clues.Err {
|
||||
return err
|
||||
}
|
||||
|
||||
func errData(err odataerrors.ODataErrorable) (string, []any, string) {
|
||||
data := make([]any, 0)
|
||||
|
||||
// Get MainError
|
||||
mainErr := err.GetErrorEscaped()
|
||||
mainMsg := ptr.Val(mainErr.GetMessage())
|
||||
|
||||
data = appendIf(data, "odataerror_code", mainErr.GetCode())
|
||||
data = appendIf(data, "odataerror_message", mainErr.GetMessage())
|
||||
data = appendIf(data, "odataerror_target", mainErr.GetTarget())
|
||||
msgConcat := ptr.Val(mainErr.GetMessage()) + ptr.Val(mainErr.GetCode())
|
||||
|
||||
for i, d := range mainErr.GetDetails() {
|
||||
pfx := fmt.Sprintf("odataerror_details_%d_", i)
|
||||
data = appendIf(data, pfx+"code", d.GetCode())
|
||||
data = appendIf(data, pfx+"message", d.GetMessage())
|
||||
data = appendIf(data, pfx+"target", d.GetTarget())
|
||||
msgConcat += ptr.Val(d.GetMessage())
|
||||
}
|
||||
|
||||
inner := mainErr.GetInnerError()
|
||||
if inner != nil {
|
||||
data = appendIf(data, "odataerror_inner_cli_req_id", inner.GetClientRequestId())
|
||||
data = appendIf(data, "odataerror_inner_req_id", inner.GetRequestId())
|
||||
}
|
||||
|
||||
return mainMsg, data, strings.ToLower(msgConcat)
|
||||
}
|
||||
|
||||
func reqData(req *http.Request) map[string]any {
|
||||
if req == nil {
|
||||
return nil
|
||||
@ -547,14 +420,6 @@ func respData(resp *http.Response) map[string]any {
|
||||
return r
|
||||
}
|
||||
|
||||
func appendIf(a []any, k string, v *string) []any {
|
||||
if v == nil {
|
||||
return a
|
||||
}
|
||||
|
||||
return append(a, k, *v)
|
||||
}
|
||||
|
||||
// ItemInfo gathers potentially useful information about a drive item,
|
||||
// and aggregates that data into a map.
|
||||
func ItemInfo(item *custom.DriveItem) map[string]any {
|
||||
@ -593,6 +458,162 @@ func ItemInfo(item *custom.DriveItem) map[string]any {
|
||||
return m
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// error parsers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type oDataErr struct {
|
||||
isODataErr bool
|
||||
Details []oDataDeets `json:"details,omitempty"`
|
||||
Inner innerErr `json:"inner,omitempty"`
|
||||
Main mainErr `json:"main,omitempty"`
|
||||
Resp apiResp `json:"resp,omitempty"`
|
||||
}
|
||||
|
||||
type oDataDeets struct {
|
||||
Code string `json:"code,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
}
|
||||
|
||||
type innerErr struct {
|
||||
ClientRequestID string `json:"clientRequestID,omitempty"`
|
||||
Code string `json:"code,omitempty"`
|
||||
Date time.Time `json:"date,omitempty"`
|
||||
OdataType string `json:"odataType,omitempty"`
|
||||
RequestID string `json:"requestID,omitempty"`
|
||||
}
|
||||
|
||||
type mainErr struct {
|
||||
Code string `json:"code,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
}
|
||||
|
||||
type apiResp struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
StatusCode int `json:"statusCode,omitempty"`
|
||||
}
|
||||
|
||||
// parses the odataerror.ODataError interface to a local
|
||||
// struct for easy logging/usage.
|
||||
func parseODataErr(err error) oDataErr {
|
||||
if err == nil {
|
||||
return oDataErr{}
|
||||
}
|
||||
|
||||
var (
|
||||
ode oDataErr
|
||||
graphODE *odataerrors.ODataError
|
||||
)
|
||||
|
||||
if !errors.As(err, &graphODE) {
|
||||
return oDataErr{}
|
||||
}
|
||||
|
||||
ode = oDataErr{
|
||||
isODataErr: true,
|
||||
Resp: apiResp{
|
||||
Message: strings.Clone(graphODE.ApiError.Message),
|
||||
StatusCode: graphODE.ApiError.ResponseStatusCode,
|
||||
},
|
||||
}
|
||||
|
||||
var (
|
||||
main = graphODE.GetErrorEscaped()
|
||||
details []odataerrors.ErrorDetailsable
|
||||
inner odataerrors.InnerErrorable
|
||||
)
|
||||
|
||||
if main != nil {
|
||||
ode.Main = mainErr{
|
||||
Code: strings.Clone(ptr.Val(main.GetCode())),
|
||||
Message: strings.Clone(ptr.Val(main.GetMessage())),
|
||||
Target: strings.Clone(ptr.Val(main.GetTarget())),
|
||||
}
|
||||
|
||||
inner = main.GetInnerError()
|
||||
details = main.GetDetails()
|
||||
}
|
||||
|
||||
if inner != nil {
|
||||
ode.Inner = innerErr{
|
||||
ClientRequestID: strings.Clone(ptr.Val(inner.GetClientRequestId())),
|
||||
Date: ptr.Val(inner.GetDate()),
|
||||
OdataType: strings.Clone(ptr.Val(inner.GetOdataType())),
|
||||
RequestID: strings.Clone(ptr.Val(inner.GetRequestId())),
|
||||
}
|
||||
|
||||
code, err := str.AnyValueToString("code", inner.GetAdditionalData())
|
||||
if err == nil {
|
||||
ode.Inner.Code = code
|
||||
}
|
||||
}
|
||||
|
||||
ode.Details = make([]oDataDeets, 0, len(details))
|
||||
|
||||
for _, deet := range details {
|
||||
d := oDataDeets{
|
||||
Code: strings.Clone(ptr.Val(deet.GetCode())),
|
||||
Message: strings.Clone(ptr.Val(deet.GetMessage())),
|
||||
Target: strings.Clone(ptr.Val(deet.GetTarget())),
|
||||
}
|
||||
|
||||
ode.Details = append(ode.Details, d)
|
||||
}
|
||||
|
||||
return ode
|
||||
}
|
||||
|
||||
func (ode oDataErr) hasErrorCode(err error, codes ...errorCode) bool {
|
||||
if !ode.isODataErr {
|
||||
return false
|
||||
}
|
||||
|
||||
cs := make([]string, len(codes))
|
||||
for i, c := range codes {
|
||||
cs[i] = string(c)
|
||||
}
|
||||
|
||||
return filters.Equal(cs).Compare(ode.Main.Code)
|
||||
}
|
||||
|
||||
func (ode oDataErr) hasInnerErrorCode(err error, codes ...errorCode) bool {
|
||||
if !ode.isODataErr {
|
||||
return false
|
||||
}
|
||||
|
||||
cs := make([]string, len(codes))
|
||||
for i, c := range codes {
|
||||
cs[i] = string(c)
|
||||
}
|
||||
|
||||
return filters.Equal(cs).Compare(ode.Inner.Code)
|
||||
}
|
||||
|
||||
// only use this as a last resort. Prefer the code or statuscode if possible.
|
||||
func (ode oDataErr) hasErrorMessage(err error, msgs ...errorMessage) bool {
|
||||
if !ode.isODataErr {
|
||||
return false
|
||||
}
|
||||
|
||||
cs := make([]string, len(msgs))
|
||||
for i, c := range msgs {
|
||||
cs[i] = string(c)
|
||||
}
|
||||
|
||||
return filters.In(cs).Compare(ode.Main.Message)
|
||||
}
|
||||
|
||||
// only use this as a last resort. Prefer the code or statuscode if possible.
|
||||
func (ode oDataErr) errMessageMatchesAllFilters(err error, fs ...filters.Filter) bool {
|
||||
if !ode.isODataErr {
|
||||
return false
|
||||
}
|
||||
|
||||
return filters.Must(ode.Main.Message, fs...)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// other helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
@ -876,16 +875,6 @@ func (suite *GraphErrorsUnitSuite) TestIsErrItemNotFound() {
|
||||
}
|
||||
|
||||
func (suite *GraphErrorsUnitSuite) TestIsErrResourceLocked() {
|
||||
innerMatch := graphTD.ODataErr("not-match")
|
||||
merr := odataerrors.NewMainError()
|
||||
inerr := odataerrors.NewInnerError()
|
||||
inerr.SetAdditionalData(map[string]any{
|
||||
"code": string(ResourceLocked),
|
||||
})
|
||||
merr.SetInnerError(inerr)
|
||||
merr.SetCode(ptr.To("not-match"))
|
||||
innerMatch.SetErrorEscaped(merr)
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
err error
|
||||
@ -913,7 +902,7 @@ func (suite *GraphErrorsUnitSuite) TestIsErrResourceLocked() {
|
||||
},
|
||||
{
|
||||
name: "matching oDataErr inner code",
|
||||
err: innerMatch,
|
||||
err: graphTD.ODataInner(string(ResourceLocked)),
|
||||
expect: assert.True,
|
||||
},
|
||||
{
|
||||
@ -941,16 +930,6 @@ func (suite *GraphErrorsUnitSuite) TestIsErrResourceLocked() {
|
||||
}
|
||||
|
||||
func (suite *GraphErrorsUnitSuite) TestIsErrSharingDisabled() {
|
||||
innerMatch := graphTD.ODataErr("not-match")
|
||||
merr := odataerrors.NewMainError()
|
||||
inerr := odataerrors.NewInnerError()
|
||||
inerr.SetAdditionalData(map[string]any{
|
||||
"code": string(sharingDisabled),
|
||||
})
|
||||
merr.SetInnerError(inerr)
|
||||
merr.SetCode(ptr.To("not-match"))
|
||||
innerMatch.SetErrorEscaped(merr)
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
err error
|
||||
@ -973,7 +952,7 @@ func (suite *GraphErrorsUnitSuite) TestIsErrSharingDisabled() {
|
||||
},
|
||||
{
|
||||
name: "matching oDataErr inner code",
|
||||
err: innerMatch,
|
||||
err: graphTD.ODataInner(string(sharingDisabled)),
|
||||
expect: assert.True,
|
||||
},
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||
"github.com/google/uuid"
|
||||
"github.com/microsoft/kiota-abstractions-go/serialization"
|
||||
kjson "github.com/microsoft/kiota-serialization-json-go"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
|
||||
@ -33,6 +35,27 @@ func ODataErrWithMsg(code, message string) *odataerrors.ODataError {
|
||||
return odErr
|
||||
}
|
||||
|
||||
func ODataInner(innerCode string) *odataerrors.ODataError {
|
||||
odErr := odataerrors.NewODataError()
|
||||
inerr := odataerrors.NewInnerError()
|
||||
merr := odataerrors.NewMainError()
|
||||
|
||||
inerr.SetAdditionalData(map[string]any{
|
||||
"code": innerCode,
|
||||
})
|
||||
inerr.SetClientRequestId(ptr.To(uuid.NewString()))
|
||||
inerr.SetOdataType(ptr.To("@odata.type"))
|
||||
inerr.SetRequestId(ptr.To("req-id"))
|
||||
|
||||
merr.SetInnerError(inerr)
|
||||
merr.SetCode(ptr.To("main code"))
|
||||
merr.SetMessage(ptr.To("main message"))
|
||||
|
||||
odErr.SetErrorEscaped(merr)
|
||||
|
||||
return odErr
|
||||
}
|
||||
|
||||
func ParseableToMap(t *testing.T, thing serialization.Parsable) map[string]any {
|
||||
sw := kjson.NewJsonSerializationWriter()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user