dal-license-server/internal/model/license_test.go
djuka dc0114e4b7 Inicijalni commit: kompletna implementacija + dokumentacija + testovi
- Kompletna Go implementacija licencnog servera (19 Go fajlova)
- Klijentski API: activate, deactivate, validate
- Admin API: CRUD licence, stats, audit log
- Admin dashboard: htmx + Go templates
- RSA-2048 potpisivanje licencnih podataka
- Rate limiting i API key autentifikacija
- MySQL migracije i seed podaci (ESIR, ARV, LIGHT_TICKET)
- Unit testovi: keygen, crypto, model, middleware (24 testa)
- Dokumentacija: SPEC.md, ARCHITECTURE.md, SETUP.md, API.md, TESTING.md, README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 07:42:25 +00:00

222 lines
5.0 KiB
Go

package model
import (
"database/sql"
"testing"
"time"
)
func TestIsExpired_Perpetual(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{Valid: false},
}
if l.IsExpired() {
t.Error("PERPETUAL licenca ne sme biti istekla")
}
}
func TestIsExpired_Active(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{
Time: time.Now().Add(24 * time.Hour),
Valid: true,
},
}
if l.IsExpired() {
t.Error("licenca koja istice sutra ne sme biti istekla")
}
}
func TestIsExpired_Expired(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{
Time: time.Now().Add(-24 * time.Hour),
Valid: true,
},
}
if !l.IsExpired() {
t.Error("licenca koja je istekla juce mora biti istekla")
}
}
func TestIsInGrace_NotExpired(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{
Time: time.Now().Add(24 * time.Hour),
Valid: true,
},
GraceDays: 30,
}
if l.IsInGrace() {
t.Error("licenca koja nije istekla ne sme biti u grace periodu")
}
}
func TestIsInGrace_InGrace(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{
Time: time.Now().Add(-5 * 24 * time.Hour), // istekla pre 5 dana
Valid: true,
},
GraceDays: 30,
}
if !l.IsInGrace() {
t.Error("licenca istekla pre 5 dana sa 30 dana grace-a mora biti u grace-u")
}
}
func TestIsInGrace_GraceExpired(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{
Time: time.Now().Add(-35 * 24 * time.Hour), // istekla pre 35 dana
Valid: true,
},
GraceDays: 30,
}
if l.IsInGrace() {
t.Error("licenca kojoj je grace prosao ne sme biti u grace-u")
}
}
func TestIsInGrace_Perpetual(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{Valid: false},
GraceDays: 30,
}
if l.IsInGrace() {
t.Error("PERPETUAL licenca ne sme biti u grace periodu")
}
}
func TestIsGraceExpired(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{
Time: time.Now().Add(-40 * 24 * time.Hour),
Valid: true,
},
GraceDays: 30,
}
if !l.IsGraceExpired() {
t.Error("grace period je prosao, mora biti expired")
}
}
func TestIsGraceExpired_Perpetual(t *testing.T) {
l := &License{
ExpiresAt: sql.NullTime{Valid: false},
GraceDays: 30,
}
if l.IsGraceExpired() {
t.Error("PERPETUAL licenca ne moze imati istekao grace")
}
}
func TestMaskedKey(t *testing.T) {
tests := []struct {
key string
prefix string
expected string
}{
{"LT-K7M2-9P4N-R3W8-J6T1", "LT-", "LT-K7M2-****-****-J6T1"},
{"ESIR-A3B5-C8D2-E7F4-G9H6", "ESIR-", "ESIR-A3B5-****-****-G9H6"},
{"ARV-X2Y3-Z4A5-B6C7-D8E9", "ARV-", "ARV-X2Y3-****-****-D8E9"},
}
for _, tt := range tests {
l := &License{LicenseKey: tt.key, ProductPrefix: tt.prefix}
got := l.MaskedKey()
if got != tt.expected {
t.Errorf("MaskedKey(%q) = %q, ocekivano %q", tt.key, got, tt.expected)
}
}
}
func TestStatusText(t *testing.T) {
tests := []struct {
name string
license License
expected string
}{
{
name: "revoked",
license: License{Revoked: true, Active: true},
expected: "Opozvana",
},
{
name: "inactive",
license: License{Active: false},
expected: "Neaktivna",
},
{
name: "active",
license: License{
Active: true,
ExpiresAt: sql.NullTime{Time: time.Now().Add(24 * time.Hour), Valid: true},
},
expected: "Aktivna",
},
{
name: "trial",
license: License{
Active: true,
LicenseType: "TRIAL",
ExpiresAt: sql.NullTime{Time: time.Now().Add(24 * time.Hour), Valid: true},
},
expected: "Trial",
},
{
name: "in_grace",
license: License{
Active: true,
ExpiresAt: sql.NullTime{Time: time.Now().Add(-5 * 24 * time.Hour), Valid: true},
GraceDays: 30,
},
expected: "Grace period",
},
{
name: "grace_expired",
license: License{
Active: true,
ExpiresAt: sql.NullTime{Time: time.Now().Add(-40 * 24 * time.Hour), Valid: true},
GraceDays: 30,
},
expected: "Istekla (grace)",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.license.StatusText()
if got != tt.expected {
t.Errorf("StatusText() = %q, ocekivano %q", got, tt.expected)
}
})
}
}
func TestStatusClass(t *testing.T) {
l := &License{Active: true, ExpiresAt: sql.NullTime{Time: time.Now().Add(24 * time.Hour), Valid: true}}
if l.StatusClass() != "status-active" {
t.Errorf("StatusClass() = %q, ocekivano 'status-active'", l.StatusClass())
}
l2 := &License{Revoked: true, Active: true}
if l2.StatusClass() != "status-revoked" {
t.Errorf("StatusClass() = %q, ocekivano 'status-revoked'", l2.StatusClass())
}
}
func TestExpiresAtFormatted(t *testing.T) {
l := &License{ExpiresAt: sql.NullTime{Valid: false}}
if l.ExpiresAtFormatted() != "Neograniceno" {
t.Errorf("ocekivano 'Neograniceno', dobijeno %q", l.ExpiresAtFormatted())
}
date := time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC)
l2 := &License{ExpiresAt: sql.NullTime{Time: date, Valid: true}}
expected := "01.04.2026"
if l2.ExpiresAtFormatted() != expected {
t.Errorf("ocekivano %q, dobijeno %q", expected, l2.ExpiresAtFormatted())
}
}