feat(v0.4): add NewLease and NewSessionID constructors
This commit is contained in:
@@ -89,3 +89,27 @@ func currentTerminal() string {
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// NewSessionID returns a session identifier in the format
|
||||
// "<hostname>-<pid>-<YYYYMMDDHHMMSS>" using the given time in UTC.
|
||||
func NewSessionID(hostname string, pid int, t time.Time) string {
|
||||
return fmt.Sprintf("%s-%d-%s", hostname, pid, t.UTC().Format("20060102150405"))
|
||||
}
|
||||
|
||||
// NewLease constructs a fresh lease for the current process. startedAt is used
|
||||
// for both StartedAt and LastHeartbeatAt.
|
||||
func NewLease(startedAt time.Time, agent, mode string) *Lease {
|
||||
hostname := currentHostname()
|
||||
pid := os.Getpid()
|
||||
return &Lease{
|
||||
SessionID: NewSessionID(hostname, pid, startedAt),
|
||||
PID: pid,
|
||||
Hostname: hostname,
|
||||
Username: currentUsername(),
|
||||
Agent: agent,
|
||||
Mode: mode,
|
||||
StartedAt: startedAt.UTC().Truncate(time.Second),
|
||||
LastHeartbeatAt: startedAt.UTC().Truncate(time.Second),
|
||||
Terminal: currentTerminal(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,3 +100,42 @@ func TestReadLeaseMissingFileReturnsErrNotExist(t *testing.T) {
|
||||
t.Errorf("expected os.ErrNotExist, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSessionIDFormat(t *testing.T) {
|
||||
now := time.Date(2026, 4, 21, 14, 30, 22, 0, time.UTC)
|
||||
id := NewSessionID("warren-desktop", 12345, now)
|
||||
want := "warren-desktop-12345-20260421143022"
|
||||
if id != want {
|
||||
t.Errorf("NewSessionID = %q, want %q", id, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewLeasePopulatesIdentity(t *testing.T) {
|
||||
now := time.Date(2026, 4, 21, 14, 30, 22, 0, time.UTC)
|
||||
l := NewLease(now, "claude", "local")
|
||||
|
||||
if l.StartedAt != now {
|
||||
t.Errorf("StartedAt: got %v, want %v", l.StartedAt, now)
|
||||
}
|
||||
if l.LastHeartbeatAt != now {
|
||||
t.Errorf("LastHeartbeatAt should be initialized to StartedAt, got %v", l.LastHeartbeatAt)
|
||||
}
|
||||
if l.Agent != "claude" {
|
||||
t.Errorf("Agent: got %q, want %q", l.Agent, "claude")
|
||||
}
|
||||
if l.Mode != "local" {
|
||||
t.Errorf("Mode: got %q, want %q", l.Mode, "local")
|
||||
}
|
||||
if l.PID != os.Getpid() {
|
||||
t.Errorf("PID: got %d, want %d", l.PID, os.Getpid())
|
||||
}
|
||||
if l.Hostname == "" {
|
||||
t.Error("Hostname should not be empty")
|
||||
}
|
||||
if l.Username == "" {
|
||||
t.Error("Username should not be empty")
|
||||
}
|
||||
if !strings.Contains(l.SessionID, l.Hostname) {
|
||||
t.Errorf("SessionID %q should contain hostname %q", l.SessionID, l.Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user