82 lines
3.2 KiB
Go
82 lines
3.2 KiB
Go
package licenseclient
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/b1tsblog/ai-disclosure-standard/pkg/licensekit"
|
|
)
|
|
|
|
func keys(t *testing.T) (ed25519.PublicKey, ed25519.PrivateKey) {
|
|
t.Helper()
|
|
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return pub, priv
|
|
}
|
|
|
|
func licenseToken(t *testing.T, mode licensekit.VerificationMode, store *licensekit.TrustStore) (string, licensekit.Claims) {
|
|
t.Helper()
|
|
pub, priv := keys(t)
|
|
store.LicenseKeys["issuer"] = licensekit.EncodeKey(pub)
|
|
now := time.Now().UTC()
|
|
claims := licensekit.Claims{Version: 1, LicenseID: "lic_1", Issuer: "vendor", Customer: "customer", Product: "product", Edition: "pro", Features: []string{"feature_a", "feature_b"}, Domains: []string{"*"}, IssuedAt: now.Unix(), ExpiresAt: now.Add(time.Hour).Unix(), Verification: licensekit.VerificationPolicy{Mode: mode, LeaseTTLSeconds: 600, OfflineGraceSeconds: 3600}}
|
|
token, err := licensekit.SignLicense(priv, "issuer", claims)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return token, claims
|
|
}
|
|
|
|
func TestOfflineClient(t *testing.T) {
|
|
store := licensekit.NewTrustStore()
|
|
token, _ := licenseToken(t, licensekit.ModeOffline, &store)
|
|
c := New(context.Background(), Config{Product: "product", Token: token, TrustStore: store, BaseURL: "https://example.org"})
|
|
if !c.Status().Licensed || !c.Has("feature_a") {
|
|
t.Fatalf("unexpected status %#v", c.Status())
|
|
}
|
|
}
|
|
|
|
func TestHybridClientUsesOnlineLeaseAndCache(t *testing.T) {
|
|
store := licensekit.NewTrustStore()
|
|
token, claims := licenseToken(t, licensekit.ModeHybrid, &store)
|
|
leasePub, leasePriv := keys(t)
|
|
store.LeaseKeys["lease"] = licensekit.EncodeKey(leasePub)
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
now := time.Now().UTC()
|
|
lease := licensekit.LeaseClaims{Version: 1, LeaseID: "lease_1", LicenseID: claims.LicenseID, Product: claims.Product, Customer: claims.Customer, Edition: claims.Edition, Features: claims.Features, Host: "example.org", IssuedAt: now.Unix(), ExpiresAt: now.Add(5 * time.Minute).Unix()}
|
|
leaseToken, err := licensekit.SignLease(leasePriv, "lease", lease)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"valid": true, "leaseToken": leaseToken})
|
|
}))
|
|
cache := filepath.Join(t.TempDir(), "lease.json")
|
|
c := New(context.Background(), Config{Product: "product", Token: token, TrustStore: store, BaseURL: "https://example.org", Mode: licensekit.ModeHybrid, ServerURL: server.URL, CacheFile: cache})
|
|
if !c.Status().Licensed || c.Status().Source != "online" {
|
|
t.Fatalf("unexpected online status %#v", c.Status())
|
|
}
|
|
server.Close()
|
|
c.Refresh(context.Background())
|
|
if !c.Status().Licensed || c.Status().Source != "cached-lease" {
|
|
t.Fatalf("unexpected cached status %#v", c.Status())
|
|
}
|
|
}
|
|
|
|
func TestOnlineModeFailsWithoutServer(t *testing.T) {
|
|
store := licensekit.NewTrustStore()
|
|
token, _ := licenseToken(t, licensekit.ModeOnline, &store)
|
|
c := New(context.Background(), Config{Product: "product", Token: token, TrustStore: store, BaseURL: "https://example.org", Mode: licensekit.ModeOnline})
|
|
if c.Status().Licensed {
|
|
t.Fatalf("online license unexpectedly active %#v", c.Status())
|
|
}
|
|
}
|