package license

import (
	"sync"
	"testing"
	"time"
)

func TestHighWaterClockNowNeverGoesBack(t *testing.T) {
	var c HighWaterClock
	future := time.Now().Add(10 * time.Minute)
	c.Observe(future)
	got := c.Now()
	if got.Before(future) {
		t.Fatalf("Now() = %v, want >= %v", got, future)
	}
}

func TestHighWaterClockBootstrapSetsFloor(t *testing.T) {
	var c HighWaterClock
	future := time.Now().Add(5 * time.Minute)
	c.Bootstrap(future)
	if c.Now().Before(future) {
		t.Fatal("Now() below bootstrap floor")
	}
}

func TestHighWaterClockZeroBootstrapIgnored(t *testing.T) {
	var c HighWaterClock
	c.Bootstrap(time.Time{})
	// mark stays zero; Now() returns wall time
	if c.Now().IsZero() {
		t.Fatal("Now() should return wall time, not zero")
	}
}

func TestHighWaterClockObserveAdvances(t *testing.T) {
	var c HighWaterClock
	future := time.Now().Add(time.Hour)
	c.Observe(future)
	if c.Now().Before(future) {
		t.Fatal("mark not advanced after Observe")
	}
}

func TestHighWaterClockConcurrentSafe(t *testing.T) {
	var c HighWaterClock
	var wg sync.WaitGroup
	for i := 0; i < 32; i++ {
		wg.Add(1)
		go func(delta int) {
			defer wg.Done()
			c.Observe(time.Now().Add(time.Duration(delta) * time.Second))
			_ = c.Now()
		}(i)
	}
	wg.Wait()
}
