// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime_test

import (
	. "runtime"
	"testing"
	"time"
)

func TestGCCPULimiter(t *testing.T) {
	const procs = 14

	// Create mock time.
	ticks := int64(0)
	advance := func(d time.Duration) int64 {
		t.Helper()
		ticks += int64(d)
		return ticks
	}

	// assistTime computes the CPU time for assists using frac of GOMAXPROCS
	// over the wall-clock duration d.
	assistTime := func(d time.Duration, frac float64) int64 {
		t.Helper()
		return int64(frac * float64(d) * procs)
	}

	l := NewGCCPULimiter(ticks, procs)

	// Do the whole test twice to make sure state doesn't leak across.
	var baseOverflow uint64 // Track total overflow across iterations.
	for i := 0; i < 2; i++ {
		t.Logf("Iteration %d", i+1)

		if l.Capacity() != procs*CapacityPerProc {
			t.Fatalf("unexpected capacity: %d", l.Capacity())
		}
		if l.Fill() != 0 {
			t.Fatalf("expected empty bucket to start")
		}

		// Test filling the bucket with just mutator time.

		l.Update(advance(10 * time.Millisecond))
		l.Update(advance(1 * time.Second))
		l.Update(advance(1 * time.Hour))
		if l.Fill() != 0 {
			t.Fatalf("expected empty bucket from only accumulating mutator time, got fill of %d cpu-ns", l.Fill())
		}

		// Test needUpdate.

		if l.NeedUpdate(advance(GCCPULimiterUpdatePeriod / 2)) {
			t.Fatal("need update even though updated half a period ago")
		}
		if !l.NeedUpdate(advance(GCCPULimiterUpdatePeriod)) {
			t.Fatal("doesn't need update even though updated 1.5 periods ago")
		}
		l.Update(advance(0))
		if l.NeedUpdate(advance(0)) {
			t.Fatal("need update even though just updated")
		}

		// Test transitioning the bucket to enable the GC.

		l.StartGCTransition(true, advance(109*time.Millisecond))
		l.FinishGCTransition(advance(2*time.Millisecond + 1*time.Microsecond))

		if expect := uint64((2*time.Millisecond + 1*time.Microsecond) * procs); l.Fill() != expect {
			t.Fatalf("expected fill of %d, got %d cpu-ns", expect, l.Fill())
		}

		// Test passing time without assists during a GC. Specifically, just enough to drain the bucket to
		// exactly procs nanoseconds (easier to get to because of rounding).
		//
		// The window we need to drain the bucket is 1/(1-2*gcBackgroundUtilization) times the current fill:
		//
		//   fill + (window * procs * gcBackgroundUtilization - window * procs * (1-gcBackgroundUtilization)) = n
		//   fill = n - (window * procs * gcBackgroundUtilization - window * procs * (1-gcBackgroundUtilization))
		//   fill = n + window * procs * ((1-gcBackgroundUtilization) - gcBackgroundUtilization)
		//   fill = n + window * procs * (1-2*gcBackgroundUtilization)
		//   window = (fill - n) / (procs * (1-2*gcBackgroundUtilization)))
		//
		// And here we want n=procs:
		factor := (1 / (1 - 2*GCBackgroundUtilization))
		fill := (2*time.Millisecond + 1*time.Microsecond) * procs
		l.Update(advance(time.Duration(factor * float64(fill-procs) / procs)))
		if l.Fill() != procs {
			t.Fatalf("expected fill %d cpu-ns from draining after a GC started, got fill of %d cpu-ns", procs, l.Fill())
		}

		// Drain to zero for the rest of the test.
		l.Update(advance(2 * procs * CapacityPerProc))
		if l.Fill() != 0 {
			t.Fatalf("expected empty bucket from draining, got fill of %d cpu-ns", l.Fill())
		}

		// Test filling up the bucket with 50% total GC work (so, not moving the bucket at all).
		l.AddAssistTime(assistTime(10*time.Millisecond, 0.5-GCBackgroundUtilization))
		l.Update(advance(10 * time.Millisecond))
		if l.Fill() != 0 {
			t.Fatalf("expected empty bucket from 50%% GC work, got fill of %d cpu-ns", l.Fill())
		}

		// Test adding to the bucket overall with 100% GC work.
		l.AddAssistTime(assistTime(time.Millisecond, 1.0-GCBackgroundUtilization))
		l.Update(advance(time.Millisecond))
		if expect := uint64(procs * time.Millisecond); l.Fill() != expect {
			t.Errorf("expected %d fill from 100%% GC CPU, got fill of %d cpu-ns", expect, l.Fill())
		}
		if l.Limiting() {
			t.Errorf("limiter is enabled after filling bucket but shouldn't be")
		}
		if t.Failed() {
			t.FailNow()
		}

		// Test filling the bucket exactly full.
		l.AddAssistTime(assistTime(CapacityPerProc-time.Millisecond, 1.0-GCBackgroundUtilization))
		l.Update(advance(CapacityPerProc - time.Millisecond))
		if l.Fill() != l.Capacity() {
			t.Errorf("expected bucket filled to capacity %d, got %d", l.Capacity(), l.Fill())
		}
		if !l.Limiting() {
			t.Errorf("limiter is not enabled after filling bucket but should be")
		}
		if l.Overflow() != 0+baseOverflow {
			t.Errorf("bucket filled exactly should not have overflow, found %d", l.Overflow())
		}
		if t.Failed() {
			t.FailNow()
		}

		// Test adding with a delta of exactly zero. That is, GC work is exactly 50% of all resources.
		// Specifically, the limiter should still be on, and no overflow should accumulate.
		l.AddAssistTime(assistTime(1*time.Second, 0.5-GCBackgroundUtilization))
		l.Update(advance(1 * time.Second))
		if l.Fill() != l.Capacity() {
			t.Errorf("expected bucket filled to capacity %d, got %d", l.Capacity(), l.Fill())
		}
		if !l.Limiting() {
			t.Errorf("limiter is not enabled after filling bucket but should be")
		}
		if l.Overflow() != 0+baseOverflow {
			t.Errorf("bucket filled exactly should not have overflow, found %d", l.Overflow())
		}
		if t.Failed() {
			t.FailNow()
		}

		// Drain the bucket by half.
		l.AddAssistTime(assistTime(CapacityPerProc, 0))
		l.Update(advance(CapacityPerProc))
		if expect := l.Capacity() / 2; l.Fill() != expect {
			t.Errorf("failed to drain to %d, got fill %d", expect, l.Fill())
		}
		if l.Limiting() {
			t.Errorf("limiter is enabled after draining bucket but shouldn't be")
		}
		if t.Failed() {
			t.FailNow()
		}

		// Test overfilling the bucket.
		l.AddAssistTime(assistTime(CapacityPerProc, 1.0-GCBackgroundUtilization))
		l.Update(advance(CapacityPerProc))
		if l.Fill() != l.Capacity() {
			t.Errorf("failed to fill to capacity %d, got fill %d", l.Capacity(), l.Fill())
		}
		if !l.Limiting() {
			t.Errorf("limiter is not enabled after overfill but should be")
		}
		if expect := uint64(CapacityPerProc * procs / 2); l.Overflow() != expect+baseOverflow {
			t.Errorf("bucket overfilled should have overflow %d, found %d", expect, l.Overflow())
		}
		if t.Failed() {
			t.FailNow()
		}

		// Test ending the cycle with some assists left over.
		l.AddAssistTime(assistTime(1*time.Millisecond, 1.0-GCBackgroundUtilization))
		l.StartGCTransition(false, advance(1*time.Millisecond))
		if l.Fill() != l.Capacity() {
			t.Errorf("failed to maintain fill to capacity %d, got fill %d", l.Capacity(), l.Fill())
		}
		if !l.Limiting() {
			t.Errorf("limiter is not enabled after overfill but should be")
		}
		if expect := uint64((CapacityPerProc/2 + time.Millisecond) * procs); l.Overflow() != expect+baseOverflow {
			t.Errorf("bucket overfilled should have overflow %d, found %d", expect, l.Overflow())
		}
		if t.Failed() {
			t.FailNow()
		}

		// Make sure the STW adds to the bucket.
		l.FinishGCTransition(advance(5 * time.Millisecond))
		if l.Fill() != l.Capacity() {
			t.Errorf("failed to maintain fill to capacity %d, got fill %d", l.Capacity(), l.Fill())
		}
		if !l.Limiting() {
			t.Errorf("limiter is not enabled after overfill but should be")
		}
		if expect := uint64((CapacityPerProc/2 + 6*time.Millisecond) * procs); l.Overflow() != expect+baseOverflow {
			t.Errorf("bucket overfilled should have overflow %d, found %d", expect, l.Overflow())
		}
		if t.Failed() {
			t.FailNow()
		}

		// Resize procs up and make sure limiting stops.
		expectFill := l.Capacity()
		l.ResetCapacity(advance(0), procs+10)
		if l.Fill() != expectFill {
			t.Errorf("failed to maintain fill at old capacity %d, got fill %d", expectFill, l.Fill())
		}
		if l.Limiting() {
			t.Errorf("limiter is enabled after resetting capacity higher")
		}
		if expect := uint64((CapacityPerProc/2 + 6*time.Millisecond) * procs); l.Overflow() != expect+baseOverflow {
			t.Errorf("bucket overflow %d should have remained constant, found %d", expect, l.Overflow())
		}
		if t.Failed() {
			t.FailNow()
		}

		// Resize procs down and make sure limiting begins again.
		// Also make sure resizing doesn't affect overflow. This isn't
		// a case where we want to report overflow, because we're not
		// actively doing work to achieve it. It's that we have fewer
		// CPU resources now.
		l.ResetCapacity(advance(0), procs-10)
		if l.Fill() != l.Capacity() {
			t.Errorf("failed lower fill to new capacity %d, got fill %d", l.Capacity(), l.Fill())
		}
		if !l.Limiting() {
			t.Errorf("limiter is disabled after resetting capacity lower")
		}
		if expect := uint64((CapacityPerProc/2 + 6*time.Millisecond) * procs); l.Overflow() != expect+baseOverflow {
			t.Errorf("bucket overflow %d should have remained constant, found %d", expect, l.Overflow())
		}
		if t.Failed() {
			t.FailNow()
		}

		// Get back to a zero state. The top of the loop will double check.
		l.ResetCapacity(advance(CapacityPerProc*procs), procs)

		// Track total overflow for future iterations.
		baseOverflow += uint64((CapacityPerProc/2 + 6*time.Millisecond) * procs)
	}
}
