216 lines
4.3 KiB
Go
216 lines
4.3 KiB
Go
package token_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.tecamino.local/paadi/licenseServer/client/hwid"
|
|
"gitea.tecamino.local/paadi/licenseServer/client/token"
|
|
)
|
|
|
|
var secret = []byte("super-secret-key-32-bytes-minimum!")
|
|
|
|
func newPair(t *testing.T) (*token.Generator, *token.Reader) {
|
|
t.Helper()
|
|
g, err := token.NewGenerator(secret)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r, err := token.NewReader(secret)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return g, r
|
|
}
|
|
|
|
// --- Expiry license tests ---
|
|
|
|
func TestExpiryLicense_Valid(t *testing.T) {
|
|
g, r := newPair(t)
|
|
tok, err := g.IssueExpiry("myapp", time.Now().Add(24*time.Hour), nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
result := r.Validate(tok, machineID)
|
|
if !result.Valid {
|
|
t.Fatalf("expected valid, got: %v", result.Error)
|
|
}
|
|
if result.ExpiresAt == nil {
|
|
t.Fatal("expected ExpiresAt to be set")
|
|
}
|
|
}
|
|
|
|
func TestExpiryLicense_Expired(t *testing.T) {
|
|
g, r := newPair(t)
|
|
tok, err := g.IssueExpiry("myapp", time.Now().Add(-1*time.Hour), nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
result := r.Validate(tok, machineID)
|
|
if result.Valid {
|
|
t.Fatal("expected invalid for expired license")
|
|
}
|
|
}
|
|
|
|
// --- Usage license tests ---
|
|
|
|
func TestUsageLicense_Valid(t *testing.T) {
|
|
g, r := newPair(t)
|
|
tok, err := g.IssueUsage("myapp", 5, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
result := r.Validate(tok, machineID)
|
|
if !result.Valid {
|
|
t.Fatalf("expected valid: %v", result.Error)
|
|
}
|
|
if *result.Remaining != 5 {
|
|
t.Fatalf("expected 5 remaining, got %d", *result.Remaining)
|
|
}
|
|
}
|
|
|
|
func TestUsageLicense_Consume(t *testing.T) {
|
|
g, r := newPair(t)
|
|
tok, err := g.IssueUsage("myapp", 3, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
for i := int64(2); i >= 0; i-- {
|
|
res, err := r.Consume(tok, machineID)
|
|
if err != nil {
|
|
t.Fatalf("consume failed: %v", err)
|
|
}
|
|
if *res.Remaining != i {
|
|
t.Fatalf("expected %d remaining, got %d", i, *res.Remaining)
|
|
}
|
|
}
|
|
|
|
// 4th consume should fail
|
|
_, err = r.Consume(tok, machineID)
|
|
if err == nil {
|
|
t.Fatal("expected error after exhausting usage")
|
|
}
|
|
}
|
|
|
|
func TestUsageLicense_Exhausted(t *testing.T) {
|
|
g, r := newPair(t)
|
|
tok, err := g.IssueUsage("myapp", 2, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
r.Consume(tok, machineID)
|
|
r.Consume(tok, machineID)
|
|
|
|
result := r.Validate(tok, machineID)
|
|
if result.Valid {
|
|
t.Fatal("expected invalid after exhausting uses")
|
|
}
|
|
}
|
|
|
|
// --- Tamper / signature tests ---
|
|
|
|
func TestTamperedToken(t *testing.T) {
|
|
g, r := newPair(t)
|
|
tok, _ := g.IssueExpiry("myapp", time.Now().Add(24*time.Hour), nil)
|
|
|
|
tampered := token.Token(string(tok) + "x")
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
result := r.Validate(tampered, machineID)
|
|
if result.Valid {
|
|
t.Fatal("tampered token should be invalid")
|
|
}
|
|
}
|
|
|
|
func TestWrongSecret(t *testing.T) {
|
|
g, _ := newPair(t)
|
|
tok, _ := g.IssueExpiry("myapp", time.Now().Add(24*time.Hour), nil)
|
|
|
|
// Reader with different secret
|
|
r2, _ := token.NewReader([]byte("different-secret-key-32-bytes-xx!"))
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
result := r2.Validate(tok, machineID)
|
|
if result.Valid {
|
|
t.Fatal("token signed with different secret should be invalid")
|
|
}
|
|
}
|
|
|
|
// --- Usage persistence ---
|
|
|
|
func TestUsageLedger_Persistence(t *testing.T) {
|
|
g, r := newPair(t)
|
|
tok, _ := g.IssueUsage("myapp", 10, nil)
|
|
|
|
fp, err := hwid.Collect()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
machineID := fp.Hash()
|
|
|
|
res, _ := r.Consume(tok, machineID)
|
|
res, _ = r.Consume(tok, machineID)
|
|
_ = res
|
|
|
|
snap := r.UsageSnapshot()
|
|
|
|
// Simulate restart: new reader, load snapshot
|
|
r2, _ := token.NewReader(secret)
|
|
for id, count := range snap {
|
|
r2.LoadUsage(id, count)
|
|
}
|
|
|
|
result := r2.Validate(tok, machineID)
|
|
if !result.Valid {
|
|
t.Fatalf("expected valid after reload: %v", result.Error)
|
|
}
|
|
if *result.Remaining != 8 {
|
|
t.Fatalf("expected 8 remaining after reloading 2 uses, got %d", *result.Remaining)
|
|
}
|
|
}
|