corso/src/internal/m365/graph/service_test.go
Keepers 7905adb8e1
test http2 stream errors, update client options (#3994)
#### Does this PR need a docs update or release note?

- [x]  No

#### Type of change

- [x] 🤖 Supportability/Tests

#### Test Plan

- [x]  Unit test
2023-08-09 19:17:38 +00:00

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")
}