blob: 15905e6f54179eb07028f7918d768b8a31859521 [file]
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package api
import (
"testing"
"time"
)
func TestPageToken(t *testing.T) {
t.Setenv("K_SERVICE", "test-service")
tests := []int{0, 1, 42, 100, 999999}
for _, n := range tests {
encoded, err := encodePageToken(n)
if err != nil {
t.Fatalf("encodePageToken(%d): %v", n, err)
}
t.Logf("encoded token for %d: %s", n, encoded)
decoded, err := decodePageToken(encoded)
if err != nil {
t.Fatalf("decodePageToken(%s): %v", encoded, err)
}
if decoded != n {
t.Errorf("decoded = %d, want %d", decoded, n)
}
}
}
func TestDecodePageTokenInvalid(t *testing.T) {
t.Setenv("K_SERVICE", "test-service")
invalidTokens := []string{
"not-hex",
"1234", // too short
"00000000000000000000000000000000", // garbage decrypted bytes
}
for _, token := range invalidTokens {
if _, err := decodePageToken(token); err == nil {
t.Errorf("decodePageToken(%s) succeeded, want error", token)
}
}
// Test expired token (49 hours ago).
expiredTime := time.Now().Add(-49 * time.Hour)
expiredToken, err := encodePageToken1(42, expiredTime)
if err != nil {
t.Fatalf("encodePageToken1: %v", err)
}
if _, err := decodePageToken(expiredToken); err == nil {
t.Error("decodePageToken succeeded for expired token, want error")
} else if want := "expired"; err.Error() != want {
t.Errorf("decodePageToken error = %v, want %s", err, want)
}
// Test future token (2 minutes in the future).
futureTime := time.Now().Add(2 * time.Minute)
futureToken, err := encodePageToken1(42, futureTime)
if err != nil {
t.Fatalf("encodePageToken1: %v", err)
}
if _, err := decodePageToken(futureToken); err == nil {
t.Error("decodePageToken succeeded for future token, want error")
} else if want := "from the future"; err.Error() != want {
t.Errorf("decodePageToken error = %v, want %s", err, want)
}
// Test overly large offset (1,000,000).
largeOffsetToken, err := encodePageToken1(maxOffset+1, time.Now())
if err != nil {
t.Fatalf("encodePageToken1: %v", err)
}
if _, err := decodePageToken(largeOffsetToken); err == nil {
t.Error("decodePageToken succeeded for large offset token, want error")
} else if want := "offset too large"; err.Error() != want {
t.Errorf("decodePageToken error = %v, want %s", err, want)
}
}
func TestStringPageToken(t *testing.T) {
t.Setenv("K_SERVICE", "test-service")
tests := []string{
"",
"a",
"hello",
"github.com/google/go-cmp/cmp",
"golang.org/x/pkgsite/internal/postgres/details_test",
"a/very/long/path/that/exceeds/the/aes/block/size/and/requires/gcm/to/encrypt/properly/without/truncation/or/errors/because/it/is/long",
}
for _, s := range tests {
encoded, err := encodeStringPageToken(s)
if err != nil {
t.Fatalf("encodeStringPageToken(%q): %v", s, err)
}
t.Logf("encoded string token for %q: %s (len=%d)", s, encoded, len(encoded))
decoded, err := decodeStringPageToken(encoded)
if err != nil {
t.Fatalf("decodeStringPageToken(%s): %v", encoded, err)
}
if decoded != s {
t.Errorf("decoded = %q, want %q", decoded, s)
}
}
}
func TestDecodeStringPageTokenInvalid(t *testing.T) {
t.Setenv("K_SERVICE", "test-service")
invalidTokens := []string{
"not-hex",
"1234", // too short
"00000000000000000000000000000000", // garbage decrypted bytes
}
for _, token := range invalidTokens {
if _, err := decodeStringPageToken(token); err == nil {
t.Errorf("decodeStringPageToken(%s) succeeded, want error", token)
}
}
// Test expired token (49 hours ago).
expiredTime := time.Now().Add(-tokenExpiry)
expiredToken, err := encodeStringPageToken1("expired-test", expiredTime)
if err != nil {
t.Fatalf("encodeStringPageToken1: %v", err)
}
if _, err := decodeStringPageToken(expiredToken); err == nil {
t.Error("decodeStringPageToken succeeded for expired token, want error")
} else if want := "expired"; err.Error() != want {
t.Errorf("decodeStringPageToken error = %v, want %s", err, want)
}
// Test future token (2 minutes in the future).
futureTime := time.Now().Add(2 * time.Minute)
futureToken, err := encodeStringPageToken1("future-test", futureTime)
if err != nil {
t.Fatalf("encodeStringPageToken1: %v", err)
}
if _, err := decodeStringPageToken(futureToken); err == nil {
t.Error("decodeStringPageToken succeeded for future token, want error")
} else if want := "from the future"; err.Error() != want {
t.Errorf("decodeStringPageToken error = %v, want %s", err, want)
}
}