Files
wonderwall/pkg/session/data_test.go
2022-10-17 12:06:03 +02:00

371 lines
10 KiB
Go

package session_test
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/nais/wonderwall/pkg/session"
)
func TestData_HasAccessToken(t *testing.T) {
data := session.Data{}
assert.False(t, data.HasAccessToken())
data.AccessToken = "some-access-token"
assert.True(t, data.HasAccessToken())
}
func TestData_HasRefreshToken(t *testing.T) {
data := session.Data{}
assert.False(t, data.HasRefreshToken())
data.RefreshToken = "some-refresh-token"
assert.True(t, data.HasRefreshToken())
}
func TestNewMetadata(t *testing.T) {
tokenLifetime := 30 * time.Minute
sessionLifetime := time.Hour
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
maxDelta := time.Second
expected := time.Now()
actual := metadata.Session.CreatedAt
assert.WithinDuration(t, expected, actual, maxDelta)
expected = time.Now().Add(sessionLifetime)
actual = metadata.Session.EndsAt
assert.WithinDuration(t, expected, actual, maxDelta)
assert.True(t, metadata.Session.TimeoutAt.IsZero())
expected = time.Now()
actual = metadata.Tokens.RefreshedAt
assert.WithinDuration(t, expected, actual, maxDelta)
expected = time.Now().Add(tokenLifetime)
actual = metadata.Tokens.ExpireAt
assert.WithinDuration(t, expected, actual, maxDelta)
}
func TestMetadata_WithTimeout(t *testing.T) {
tokenLifetime := 30 * time.Minute
sessionLifetime := time.Hour
sessionInactivityTimeout := 15 * time.Minute
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
metadata.WithTimeout(sessionInactivityTimeout)
maxDelta := time.Second
assert.False(t, metadata.Session.TimeoutAt.IsZero())
expected := time.Now().Add(sessionInactivityTimeout)
actual := metadata.Session.TimeoutAt
assert.WithinDuration(t, expected, actual, maxDelta)
}
func TestMetadata_IsExpired(t *testing.T) {
t.Run("expired", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
ExpireAt: time.Now().Add(-time.Second),
},
}
assert.True(t, metadata.IsExpired())
})
t.Run("not expired", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
ExpireAt: time.Now().Add(time.Second),
},
}
assert.False(t, metadata.IsExpired())
})
}
func TestMetadata_IsRefreshOnCooldown(t *testing.T) {
t.Run("delta to last refresh below minimum interval", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(time.Minute),
},
}
assert.True(t, metadata.IsRefreshOnCooldown())
})
t.Run("delta to last refresh above minimum interval", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now().Add(-2 * time.Minute),
ExpireAt: time.Now().Add(time.Minute),
},
}
assert.False(t, metadata.IsRefreshOnCooldown())
})
}
func TestMetadata_NextRefresh(t *testing.T) {
t.Run("delta to last refresh below minimum interval", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(time.Minute),
},
}
assert.True(t, metadata.IsRefreshOnCooldown())
})
t.Run("delta to last refresh above minimum interval", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now().Add(-2 * time.Minute),
ExpireAt: time.Now().Add(time.Minute),
},
}
assert.False(t, metadata.IsRefreshOnCooldown())
})
}
func TestMetadata_Refresh(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(time.Minute),
},
}
prevRefreshedAt := metadata.Tokens.RefreshedAt
prevExpireAt := metadata.Tokens.ExpireAt
nextExpirySeconds := int64((2 * time.Minute).Seconds())
metadata.Refresh(nextExpirySeconds)
assert.True(t, metadata.Tokens.RefreshedAt.After(prevRefreshedAt))
assert.True(t, metadata.Tokens.ExpireAt.After(prevExpireAt))
}
func TestMetadata_RefreshCooldown(t *testing.T) {
t.Run("token lifetime less than interval", func(t *testing.T) {
tokenLifetime := time.Minute
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(tokenLifetime),
},
}
expected := time.Now().Add(tokenLifetime / 2)
assert.WithinDuration(t, expected, metadata.RefreshCooldown(), time.Second)
})
t.Run("token lifetime longer than interval", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(time.Hour),
},
}
expected := metadata.Tokens.RefreshedAt.Add(session.RefreshMinInterval)
assert.WithinDuration(t, expected, metadata.RefreshCooldown(), time.Second)
})
}
func TestMetadata_ShouldRefresh(t *testing.T) {
t.Run("refresh is on cooldown", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(time.Minute),
},
}
assert.False(t, metadata.ShouldRefresh())
})
t.Run("token is not within expiry range", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(time.Hour),
},
}
assert.False(t, metadata.ShouldRefresh())
})
t.Run("token is about to expire", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now().Add(-5 * time.Minute),
ExpireAt: time.Now().Add(time.Minute),
},
}
assert.True(t, metadata.ShouldRefresh())
})
t.Run("token has expired", func(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now().Add(-5 * time.Minute),
ExpireAt: time.Now().Add(-5 * time.Minute),
},
}
assert.True(t, metadata.ShouldRefresh())
})
}
func TestMetadata_TokenLifetime(t *testing.T) {
metadata := session.Metadata{
Tokens: session.MetadataTokens{
RefreshedAt: time.Now(),
ExpireAt: time.Now().Add(time.Minute),
},
}
assert.Equal(t, time.Minute, metadata.TokenLifetime().Truncate(time.Second))
}
func TestMetadata_Verbose(t *testing.T) {
tokenLifetime := 30 * time.Minute
sessionLifetime := time.Hour
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
verbose := metadata.Verbose()
maxDelta := time.Second
expected := time.Now().Add(sessionLifetime)
actual := time.Now().Add(durationSeconds(verbose.Session.EndsInSeconds))
assert.WithinDuration(t, expected, actual, maxDelta)
expected = time.Now().Add(tokenLifetime)
actual = time.Now().Add(durationSeconds(verbose.Tokens.ExpireInSeconds))
assert.WithinDuration(t, expected, actual, maxDelta)
assert.True(t, verbose.Session.Active)
assert.True(t, verbose.Session.TimeoutAt.IsZero())
assert.Equal(t, int64(-1), verbose.Session.TimeoutInSeconds)
}
func TestMetadata_VerboseWithRefresh(t *testing.T) {
tokenLifetime := 30 * time.Minute
sessionLifetime := time.Hour
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
verbose := metadata.VerboseWithRefresh()
maxDelta := time.Second
expected := time.Now().Add(sessionLifetime)
actual := time.Now().Add(durationSeconds(verbose.Session.EndsInSeconds))
assert.WithinDuration(t, expected, actual, maxDelta)
expected = time.Now().Add(tokenLifetime)
actual = time.Now().Add(durationSeconds(verbose.Tokens.ExpireInSeconds))
assert.WithinDuration(t, expected, actual, maxDelta)
expected = time.Now().Add(tokenLifetime).Add(-session.RefreshLeeway)
actual = time.Now().Add(durationSeconds(verbose.Tokens.NextAutoRefreshInSeconds))
assert.WithinDuration(t, expected, actual, maxDelta)
t.Run("refresh on cooldown", func(t *testing.T) {
assert.True(t, verbose.Tokens.RefreshCooldown)
expected = time.Now().Add(session.RefreshMinInterval)
actual = time.Now().Add(durationSeconds(verbose.Tokens.RefreshCooldownSeconds))
assert.WithinDuration(t, expected, actual, maxDelta)
})
t.Run("refresh not on cooldown", func(t *testing.T) {
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
metadata.Tokens.RefreshedAt = time.Now().Add(-5 * time.Minute)
verbose := metadata.VerboseWithRefresh()
assert.False(t, verbose.Tokens.RefreshCooldown)
assert.Equal(t, int64(0), verbose.Tokens.RefreshCooldownSeconds)
})
}
func TestMetadata_Verbose_WithTimeout(t *testing.T) {
tokenLifetime := 30 * time.Minute
sessionLifetime := time.Hour
timeout := 15 * time.Minute
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
metadata.WithTimeout(timeout)
maxDelta := time.Second
verbose := metadata.Verbose()
assert.True(t, verbose.Session.Active)
assert.False(t, verbose.Session.TimeoutAt.IsZero())
expected := time.Now().Add(timeout)
actual := verbose.Session.TimeoutAt
assert.WithinDuration(t, expected, actual, maxDelta)
expected = time.Now().Add(durationSeconds(verbose.Session.TimeoutInSeconds))
actual = verbose.Session.TimeoutAt
assert.WithinDuration(t, expected, actual, maxDelta)
}
func TestMetadata_ExtendTimeout(t *testing.T) {
tokenLifetime := 30 * time.Minute
sessionLifetime := time.Hour
timeout := 15 * time.Minute
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
metadata.WithTimeout(timeout)
previousTimeoutAt := metadata.Session.TimeoutAt
time.Sleep(100 * time.Millisecond)
metadata.ExtendTimeout(timeout)
assert.True(t, metadata.Session.TimeoutAt.After(previousTimeoutAt))
}
func TestMetadata_IsTimedOut(t *testing.T) {
tokenLifetime := 30 * time.Minute
sessionLifetime := time.Hour
t.Run("timeout is zero", func(t *testing.T) {
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
assert.False(t, metadata.IsTimedOut())
})
t.Run("timeout is non-zero", func(t *testing.T) {
timeout := 15 * time.Minute
metadata := session.NewMetadata(tokenLifetime, sessionLifetime)
metadata.WithTimeout(timeout)
assert.False(t, metadata.IsTimedOut())
metadata.WithTimeout(-timeout)
assert.True(t, metadata.IsTimedOut())
})
}
func durationSeconds(seconds int64) time.Duration {
return time.Duration(seconds) * time.Second
}