#### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🤖 Supportability/Tests #### Test Plan - [x] ⚡ Unit test
243 lines
6.7 KiB
Go
243 lines
6.7 KiB
Go
package graph
|
|
|
|
import (
|
|
"net/http"
|
|
"syscall"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/alcionai/clues"
|
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
|
"github.com/microsoftgraph/msgraph-sdk-go/users"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/alcionai/corso/src/internal/tester"
|
|
"github.com/alcionai/corso/src/internal/tester/tconfig"
|
|
"github.com/alcionai/corso/src/pkg/account"
|
|
)
|
|
|
|
type GraphIntgSuite struct {
|
|
tester.Suite
|
|
fakeCredentials account.M365Config
|
|
credentials account.M365Config
|
|
}
|
|
|
|
func TestGraphIntgSuite(t *testing.T) {
|
|
suite.Run(t, &GraphIntgSuite{
|
|
Suite: tester.NewIntegrationSuite(
|
|
t,
|
|
[][]string{tconfig.M365AcctCredEnvs}),
|
|
})
|
|
}
|
|
|
|
func (suite *GraphIntgSuite) SetupSuite() {
|
|
t := suite.T()
|
|
|
|
ctx, flush := tester.NewContext(t)
|
|
defer flush()
|
|
|
|
fakeAcct := tconfig.NewFakeM365Account(t)
|
|
acct := tconfig.NewM365Account(t)
|
|
|
|
m365, err := fakeAcct.M365Config()
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
suite.fakeCredentials = m365
|
|
|
|
m365, err = acct.M365Config()
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
suite.credentials = m365
|
|
|
|
InitializeConcurrencyLimiter(ctx, false, 0)
|
|
}
|
|
|
|
func (suite *GraphIntgSuite) TestCreateAdapter() {
|
|
t := suite.T()
|
|
adpt, err := CreateAdapter(
|
|
suite.fakeCredentials.AzureTenantID,
|
|
suite.fakeCredentials.AzureClientID,
|
|
suite.fakeCredentials.AzureClientSecret)
|
|
|
|
assert.NoError(t, err, clues.ToCore(err))
|
|
assert.NotNil(t, adpt)
|
|
}
|
|
|
|
func (suite *GraphIntgSuite) TestHTTPClient() {
|
|
table := []struct {
|
|
name string
|
|
opts []Option
|
|
check func(*testing.T, *http.Client)
|
|
checkConfig func(*testing.T, *clientConfig)
|
|
}{
|
|
{
|
|
name: "no options",
|
|
opts: []Option{},
|
|
check: func(t *testing.T, c *http.Client) {
|
|
assert.Equal(t, defaultHTTPClientTimeout, c.Timeout, "default timeout")
|
|
},
|
|
checkConfig: func(t *testing.T, c *clientConfig) {
|
|
assert.Equal(t, defaultDelay, c.minDelay, "default delay")
|
|
assert.Equal(t, defaultMaxRetries, c.maxRetries, "max retries")
|
|
assert.Equal(t, defaultMaxRetries, c.maxConnectionRetries, "max connection retries")
|
|
},
|
|
},
|
|
{
|
|
name: "configured options",
|
|
opts: []Option{
|
|
NoTimeout(),
|
|
MaxRetries(4),
|
|
MaxConnectionRetries(2),
|
|
MinimumBackoff(999 * time.Millisecond),
|
|
},
|
|
check: func(t *testing.T, c *http.Client) {
|
|
// FIXME: Change to 0 one upstream issue is fixed
|
|
assert.Equal(t, time.Duration(48*time.Hour), c.Timeout, "unlimited timeout")
|
|
},
|
|
checkConfig: func(t *testing.T, c *clientConfig) {
|
|
assert.Equal(t, 999*time.Millisecond, c.minDelay, "minimum delay")
|
|
assert.Equal(t, 4, c.maxRetries, "max retries")
|
|
assert.Equal(t, 2, c.maxConnectionRetries, "max connection retries")
|
|
},
|
|
},
|
|
{
|
|
name: "below minimums",
|
|
opts: []Option{
|
|
NoTimeout(),
|
|
MaxRetries(-1),
|
|
MaxConnectionRetries(-1),
|
|
MinimumBackoff(0),
|
|
},
|
|
check: func(t *testing.T, c *http.Client) {
|
|
// FIXME: Change to 0 one upstream issue is fixed
|
|
assert.Equal(t, time.Duration(48*time.Hour), c.Timeout, "unlimited timeout")
|
|
},
|
|
checkConfig: func(t *testing.T, c *clientConfig) {
|
|
assert.Equal(t, 100*time.Millisecond, c.minDelay, "minimum delay")
|
|
assert.Equal(t, 0, c.maxRetries, "max retries")
|
|
assert.Equal(t, 0, c.maxConnectionRetries, "max connection retries")
|
|
},
|
|
},
|
|
{
|
|
name: "above maximums",
|
|
opts: []Option{
|
|
NoTimeout(),
|
|
MaxRetries(9001),
|
|
MaxConnectionRetries(9001),
|
|
MinimumBackoff(999 * time.Second),
|
|
},
|
|
check: func(t *testing.T, c *http.Client) {
|
|
// FIXME: Change to 0 one upstream issue is fixed
|
|
assert.Equal(t, time.Duration(48*time.Hour), c.Timeout, "unlimited timeout")
|
|
},
|
|
checkConfig: func(t *testing.T, c *clientConfig) {
|
|
assert.Equal(t, 5*time.Second, c.minDelay, "minimum delay")
|
|
assert.Equal(t, 5, c.maxRetries, "max retries")
|
|
assert.Equal(t, 5, c.maxConnectionRetries, "max connection retries")
|
|
},
|
|
},
|
|
}
|
|
for _, test := range table {
|
|
suite.Run(test.name, func() {
|
|
t := suite.T()
|
|
|
|
cli, cc := KiotaHTTPClient(test.opts...)
|
|
assert.NotNil(t, cli)
|
|
test.check(t, cli)
|
|
test.checkConfig(t, cc)
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *GraphIntgSuite) TestSerializationEndPoint() {
|
|
t := suite.T()
|
|
adpt, err := CreateAdapter(
|
|
suite.fakeCredentials.AzureTenantID,
|
|
suite.fakeCredentials.AzureClientID,
|
|
suite.fakeCredentials.AzureClientSecret)
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
serv := NewService(adpt)
|
|
email := models.NewMessage()
|
|
subject := "TestSerializationEndPoint"
|
|
email.SetSubject(&subject)
|
|
|
|
byteArray, err := serv.Serialize(email)
|
|
assert.NoError(t, err, clues.ToCore(err))
|
|
assert.NotNil(t, byteArray)
|
|
t.Log(string(byteArray))
|
|
}
|
|
|
|
func (suite *GraphIntgSuite) TestAdapterWrap_catchesPanic() {
|
|
t := suite.T()
|
|
|
|
ctx, flush := tester.NewContext(t)
|
|
defer flush()
|
|
|
|
url := "https://graph.microsoft.com/fnords/beaux/regard"
|
|
|
|
// the panics should get caught and returned as errors
|
|
alwaysPanicMiddleware := mwForceResp{
|
|
alternate: func(req *http.Request) (bool, *http.Response, error) {
|
|
panic(clues.New("intentional panic"))
|
|
},
|
|
}
|
|
|
|
adpt, err := CreateAdapter(
|
|
suite.credentials.AzureTenantID,
|
|
suite.credentials.AzureClientID,
|
|
suite.credentials.AzureClientSecret,
|
|
appendMiddleware(&alwaysPanicMiddleware))
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
// the query doesn't matter
|
|
_, err = users.NewItemCalendarsItemEventsDeltaRequestBuilder(url, adpt).Get(ctx, nil)
|
|
require.Error(t, err, clues.ToCore(err))
|
|
require.Contains(t, err.Error(), "panic", clues.ToCore(err))
|
|
|
|
// the query doesn't matter
|
|
_, err = NewService(adpt).Client().Users().Get(ctx, nil)
|
|
require.Error(t, err, clues.ToCore(err))
|
|
require.Contains(t, err.Error(), "panic", clues.ToCore(err))
|
|
}
|
|
|
|
func (suite *GraphIntgSuite) TestAdapterWrap_retriesConnectionClose() {
|
|
t := suite.T()
|
|
|
|
ctx, flush := tester.NewContext(t)
|
|
defer flush()
|
|
|
|
url := "https://graph.microsoft.com/fnords/beaux/regard"
|
|
count := 0
|
|
|
|
// the panics should get caught and returned as errors
|
|
alwaysECONNRESET := mwForceResp{
|
|
err: syscall.ECONNRESET,
|
|
alternate: func(req *http.Request) (bool, *http.Response, error) {
|
|
count++
|
|
return false, nil, nil
|
|
},
|
|
}
|
|
|
|
adpt, err := CreateAdapter(
|
|
suite.credentials.AzureTenantID,
|
|
suite.credentials.AzureClientID,
|
|
suite.credentials.AzureClientSecret,
|
|
appendMiddleware(&alwaysECONNRESET))
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
// the query doesn't matter
|
|
_, err = users.NewItemCalendarsItemEventsDeltaRequestBuilder(url, adpt).Get(ctx, nil)
|
|
require.ErrorIs(t, err, syscall.ECONNRESET, clues.ToCore(err))
|
|
require.Equal(t, 16, count, "number of retries")
|
|
|
|
count = 0
|
|
|
|
// the query doesn't matter
|
|
_, err = NewService(adpt).Client().Users().Get(ctx, nil)
|
|
require.ErrorIs(t, err, syscall.ECONNRESET, clues.ToCore(err))
|
|
require.Equal(t, 16, count, "number of retries")
|
|
}
|