GC: Use of Ptr extension (#2477)

## Description
Use of Pointer package in /connector/exchange

<!-- Insert PR description-->

## Does this PR need a docs update or release note?
Wanted to extend the package to generics, but it is incomplete

- [x]  No 

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature


## Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* related  #2474<issue>

## Test Plan

- [x]  Unit test
This commit is contained in:
Danny 2023-02-10 16:10:22 -05:00 committed by GitHub
parent 6b6f684119
commit eda4699d1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 132 additions and 53 deletions

View File

@ -1,13 +1,20 @@
package ptr
// Val helper method for unwrapping strings
// ptr package is a common package used for pointer
// access and deserialization.
// Val Generic function for dereferencing pointers.
// Microsoft Graph saves many variables as string pointers.
// Function will safely check if the point is nil prior to
// dereferencing the pointer. If the pointer is nil,
// an empty string is returned.
func Val(ptr *string) string {
// an empty version of the object is returned.
// Operation does not work on Nested objects.
// For example:
// *evt.GetEnd().GetDateTime() will still cause a panic
// if evt is nil or GetEnd() is nil
func Val[T any](ptr *T) T {
if ptr == nil {
return ""
return *new(T)
}
return *ptr

View File

@ -0,0 +1,99 @@
package ptr_test
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/common/ptr"
)
type PointerSuite struct {
suite.Suite
}
func TestPointerSuite(t *testing.T) {
suite.Run(t, new(PointerSuite))
}
// TestVal checks to ptr derefencing for the
// following types:
// - *string
// - *bool
// - *time.Time
func (suite *PointerSuite) TestVal() {
var (
t = suite.T()
created *time.Time
testString *string
testBool *bool
testInt *int
testInt32 *int32
testInt64 *int64
)
// String Checks
subject := ptr.Val(testString)
assert.Empty(t, subject)
hello := "Hello World"
testString = &hello
subject = ptr.Val(testString)
t.Logf("Received: %s", subject)
assert.NotEmpty(t, subject)
// Time Checks
myTime := ptr.Val(created)
assert.Empty(t, myTime)
assert.NotNil(t, myTime)
now := time.Now()
created = &now
myTime = ptr.Val(created)
assert.NotEmpty(t, myTime)
// Bool Checks
truth := true
myBool := ptr.Val(testBool)
assert.NotNil(t, myBool)
assert.False(t, myBool)
testBool = &truth
myBool = ptr.Val(testBool)
assert.NotNil(t, myBool)
assert.True(t, myBool)
// Int checks
myInt := ptr.Val(testInt)
myInt32 := ptr.Val(testInt32)
myInt64 := ptr.Val(testInt64)
assert.NotNil(t, myInt)
assert.NotNil(t, myInt32)
assert.NotNil(t, myInt64)
assert.Empty(t, myInt)
assert.Empty(t, myInt32)
assert.Empty(t, myInt64)
num := 4071
num32 := int32(num * 32)
num64 := int64(num * 2048)
testInt = &num
testInt32 = &num32
testInt64 = &num64
myInt = ptr.Val(testInt)
myInt32 = ptr.Val(testInt32)
myInt64 = ptr.Val(testInt64)
assert.NotNil(t, myInt)
assert.NotNil(t, myInt32)
assert.NotNil(t, myInt64)
assert.NotEmpty(t, myInt)
assert.NotEmpty(t, myInt32)
assert.NotEmpty(t, myInt64)
}

View File

@ -3,7 +3,6 @@ package api
import (
"context"
"fmt"
"time"
"github.com/alcionai/clues"
"github.com/hashicorp/go-multierror"
@ -13,6 +12,7 @@ import (
"github.com/microsoftgraph/msgraph-sdk-go/users"
"github.com/pkg/errors"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/connector/graph/api"
"github.com/alcionai/corso/src/internal/connector/support"
@ -317,16 +317,8 @@ func (c Contacts) Serialize(
// ---------------------------------------------------------------------------
func ContactInfo(contact models.Contactable) *details.ExchangeInfo {
name := ""
created := time.Time{}
if contact.GetDisplayName() != nil {
name = *contact.GetDisplayName()
}
if contact.GetCreatedDateTime() != nil {
created = *contact.GetCreatedDateTime()
}
name := ptr.Val(contact.GetDisplayName())
created := ptr.Val(contact.GetCreatedDateTime())
return &details.ExchangeInfo{
ItemType: details.ExchangeContact,

View File

@ -14,6 +14,7 @@ import (
"github.com/pkg/errors"
"github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/connector/graph/api"
"github.com/alcionai/corso/src/internal/connector/support"
@ -390,11 +391,12 @@ func (c CalendarDisplayable) GetParentFolderId() *string {
func EventInfo(evt models.Eventable) *details.ExchangeInfo {
var (
organizer, subject string
recurs bool
start = time.Time{}
end = time.Time{}
created = time.Time{}
organizer string
subject = ptr.Val(evt.GetSubject())
recurs bool
start = time.Time{}
end = time.Time{}
created = ptr.Val(evt.GetCreatedDateTime())
)
if evt.GetOrganizer() != nil &&
@ -405,10 +407,6 @@ func EventInfo(evt models.Eventable) *details.ExchangeInfo {
GetAddress()
}
if evt.GetSubject() != nil {
subject = *evt.GetSubject()
}
if evt.GetRecurrence() != nil {
recurs = true
}
@ -437,10 +435,6 @@ func EventInfo(evt models.Eventable) *details.ExchangeInfo {
}
}
if evt.GetCreatedDateTime() != nil {
created = *evt.GetCreatedDateTime()
}
return &details.ExchangeInfo{
ItemType: details.ExchangeEvent,
Organizer: organizer,

View File

@ -3,7 +3,6 @@ package api
import (
"context"
"fmt"
"time"
"github.com/alcionai/clues"
"github.com/hashicorp/go-multierror"
@ -13,6 +12,7 @@ import (
"github.com/microsoftgraph/msgraph-sdk-go/users"
"github.com/pkg/errors"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/connector/graph/api"
"github.com/alcionai/corso/src/internal/connector/support"
@ -348,9 +348,9 @@ func (c Mail) Serialize(
func MailInfo(msg models.Messageable) *details.ExchangeInfo {
sender := ""
subject := ""
received := time.Time{}
created := time.Time{}
subject := ptr.Val(msg.GetSubject())
received := ptr.Val(msg.GetReceivedDateTime())
created := ptr.Val(msg.GetCreatedDateTime())
if msg.GetSender() != nil &&
msg.GetSender().GetEmailAddress() != nil &&
@ -358,18 +358,6 @@ func MailInfo(msg models.Messageable) *details.ExchangeInfo {
sender = *msg.GetSender().GetEmailAddress().GetAddress()
}
if msg.GetSubject() != nil {
subject = *msg.GetSubject()
}
if msg.GetReceivedDateTime() != nil {
received = *msg.GetReceivedDateTime()
}
if msg.GetCreatedDateTime() != nil {
created = *msg.GetCreatedDateTime()
}
return &details.ExchangeInfo{
ItemType: details.ExchangeMail,
Sender: sender,

View File

@ -25,7 +25,8 @@ const (
)
func attachmentType(attachment models.Attachmentable) models.AttachmentType {
switch *attachment.GetOdataType() {
attachmentType := ptr.Val(attachment.GetOdataType())
switch attachmentType {
case fileAttachmentOdataValue:
return models.FILE_ATTACHMENTTYPE
case itemAttachmentOdataValue:

View File

@ -11,6 +11,7 @@ import (
"github.com/pkg/errors"
"github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/connector/exchange/api"
"github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/connector/support"
@ -71,7 +72,7 @@ func RestoreExchangeContact(
response, err := service.Client().UsersById(user).ContactFoldersById(destination).Contacts().Post(ctx, contact, nil)
if err != nil {
name := *contact.GetGivenName()
name := ptr.Val(contact.GetGivenName())
return nil, errors.Wrap(
err,
@ -146,7 +147,8 @@ func RestoreExchangeEvent(
errs = support.WrapAndAppend(
fmt.Sprintf(
"uploading attachment for message %s: %s",
*transformedEvent.GetId(), support.ConnectorStackErrorTrace(err),
ptr.Val(transformedEvent.GetId()),
support.ConnectorStackErrorTrace(err),
),
err,
errs,
@ -283,12 +285,8 @@ func SendMailToBackStore(
for _, attachment := range attached {
if err := uploadAttachment(ctx, uploader, attachment); err != nil {
if attachment.GetOdataType() != nil &&
*attachment.GetOdataType() == "#microsoft.graph.itemAttachment" {
var name string
if attachment.GetName() != nil {
name = *attachment.GetName()
}
if ptr.Val(attachment.GetOdataType()) == "#microsoft.graph.itemAttachment" {
name := ptr.Val(attachment.GetName())
logger.Ctx(ctx).Infow(
"item attachment upload not successful. content not accepted by M365 server",