All checks were successful
Server Check Build (NixCN CMS) TeamCity build finished
Signed-off-by: Asai Neko <sugar@sne.moe>
173 lines
4.6 KiB
Go
173 lines
4.6 KiB
Go
package testutil
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"nixcn-cms/data"
|
|
"nixcn-cms/internal/cryptography"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/glebarez/sqlite"
|
|
"github.com/google/uuid"
|
|
"github.com/redis/go-redis/v9"
|
|
"github.com/spf13/viper"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
// TestAESKey is a 32-byte AES key used for client_secret_key in tests.
|
|
const TestAESKey = "testkey1234567890123456789012345"
|
|
|
|
// TestKYCAESKey is a 16-byte AES key used for kyc_info_key in tests.
|
|
const TestKYCAESKey = "testkyckey123456"
|
|
|
|
// TestClientID is the OAuth client ID used across tests.
|
|
const TestClientID = "test-client"
|
|
|
|
// TestClientSecret is the plaintext client secret used in tests.
|
|
const TestClientSecret = "testsecret-32bytes-padded-here!!"
|
|
|
|
// SetupTestDB initialises an in-memory SQLite database and assigns it to
|
|
// data.Database. It auto-migrates all models including Agenda.
|
|
func SetupTestDB(t *testing.T) {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("SetupTestDB: open sqlite: %v", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(
|
|
&data.User{},
|
|
&data.Event{},
|
|
&data.Attendance{},
|
|
&data.Client{},
|
|
&data.Kyc{},
|
|
&data.Agenda{},
|
|
); err != nil {
|
|
t.Fatalf("SetupTestDB: auto-migrate: %v", err)
|
|
}
|
|
|
|
data.Database = db
|
|
|
|
t.Cleanup(func() {
|
|
sqlDB, _ := db.DB()
|
|
_ = sqlDB.Close()
|
|
data.Database = nil
|
|
})
|
|
}
|
|
|
|
// SetupTestRedis starts an in-memory miniredis server and assigns it to
|
|
// data.Redis. It returns the miniredis instance for time manipulation.
|
|
func SetupTestRedis(t *testing.T) *miniredis.Miniredis {
|
|
t.Helper()
|
|
mr, err := miniredis.Run()
|
|
if err != nil {
|
|
t.Fatalf("SetupTestRedis: start miniredis: %v", err)
|
|
}
|
|
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
data.Redis = rdb
|
|
|
|
t.Cleanup(func() {
|
|
_ = rdb.Close()
|
|
mr.Close()
|
|
data.Redis = nil
|
|
})
|
|
|
|
return mr
|
|
}
|
|
|
|
// SetupViper configures the minimum viper keys needed by internal packages
|
|
// and services during tests.
|
|
func SetupViper(t *testing.T) {
|
|
t.Helper()
|
|
viper.Reset()
|
|
viper.Set("server.application", "test-app")
|
|
viper.Set("server.debug_mode", true)
|
|
viper.Set("server.external_url", "http://localhost:8080")
|
|
viper.Set("secrets.client_secret_key", TestAESKey)
|
|
viper.Set("secrets.kyc_info_key", TestKYCAESKey)
|
|
viper.Set("secrets.turnstile_secret", "test-turnstile-secret")
|
|
viper.Set("ttl.auth_code_ttl", 10*time.Minute)
|
|
viper.Set("ttl.access_ttl", 15*time.Minute)
|
|
viper.Set("ttl.refresh_ttl", 7*24*time.Hour)
|
|
viper.Set("ttl.checkin_code_ttl", 5*time.Minute)
|
|
viper.Set("kyc.ali_access_key_id", "test-key-id")
|
|
viper.Set("kyc.ali_access_key_secret", "test-key-secret")
|
|
viper.Set("kyc.passport_reader_public_key", "test-pub")
|
|
viper.Set("kyc.passport_reader_secret", "test-secret")
|
|
|
|
t.Cleanup(func() { viper.Reset() })
|
|
}
|
|
|
|
// Setup is a convenience that calls SetupViper, SetupTestDB, and
|
|
// SetupTestRedis, returning the miniredis instance.
|
|
func Setup(t *testing.T) *miniredis.Miniredis {
|
|
t.Helper()
|
|
SetupViper(t)
|
|
SetupTestDB(t)
|
|
return SetupTestRedis(t)
|
|
}
|
|
|
|
// SeedClient creates a test OAuth client in the database and returns it.
|
|
func SeedClient(t *testing.T) *data.Client {
|
|
t.Helper()
|
|
ctx := t.Context()
|
|
|
|
enc, err := cryptography.AESCBCEncrypt([]byte(TestClientSecret), []byte(TestAESKey))
|
|
if err != nil {
|
|
t.Fatalf("SeedClient: encrypt secret: %v", err)
|
|
}
|
|
|
|
redirectURIs := []string{"http://localhost/callback"}
|
|
urisJSON, _ := json.Marshal(redirectURIs)
|
|
|
|
client := &data.Client{
|
|
UUID: uuid.New(),
|
|
ClientId: TestClientID,
|
|
ClientSecret: enc,
|
|
ClientName: "Test Client",
|
|
RedirectUri: urisJSON,
|
|
}
|
|
|
|
if err := data.Database.WithContext(ctx).Create(client).Error; err != nil {
|
|
t.Fatalf("SeedClient: create: %v", err)
|
|
}
|
|
|
|
return client
|
|
}
|
|
|
|
// RandomEmail returns a unique email address for use in tests.
|
|
func RandomEmail() string {
|
|
return uuid.New().String() + "@test.com"
|
|
}
|
|
|
|
// SetupWithAuth is a convenience that calls Setup and SeedClient, then returns
|
|
// the miniredis instance and the seeded client.
|
|
func SetupWithAuth(t *testing.T) (*miniredis.Miniredis, *data.Client) {
|
|
t.Helper()
|
|
mr := Setup(t)
|
|
client := SeedClient(t)
|
|
return mr, client
|
|
}
|
|
|
|
// SeedUser creates a test user in the database and returns it.
|
|
func SeedUser(t *testing.T, email string, permLevel uint) *data.User {
|
|
t.Helper()
|
|
ctx := t.Context()
|
|
u := data.NewUser(
|
|
data.WithEmail(email),
|
|
data.WithUsername("user-"+uuid.New().String()[:8]),
|
|
data.WithPermissionLevel(permLevel),
|
|
data.WithNickname("Test User"),
|
|
)
|
|
if err := u.Create(ctx); err != nil {
|
|
t.Fatalf("SeedUser: create %q: %v", email, err)
|
|
}
|
|
return u
|
|
}
|