289 lines
7.5 KiB
Go
289 lines
7.5 KiB
Go
//go:build windows
|
|
|
|
package main
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestControllerNormalBoostRestoredAtExit(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(10, 150, PriorityClassBelowNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassHigh)
|
|
c.Shutdown()
|
|
assertPriority(t, p, PriorityClassBelowNormal)
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerHeavyRemainsTrackedBelowThresholdAndDuringReadFailure(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
p := f.add(20, 50, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
g.info.RSS = 1
|
|
c.Step()
|
|
assertPriority(t, g, PriorityClassHigh)
|
|
g.readable = false
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassIdle)
|
|
g.alive = false
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassNormal)
|
|
c.Shutdown()
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerProtectedHeavyStillEnablesMode(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
g.writable = false
|
|
p := f.add(20, 50, PriorityClassNormal)
|
|
c := testController(f)
|
|
r := c.Step()
|
|
assertPriority(t, g, PriorityClassNormal)
|
|
assertPriority(t, p, PriorityClassIdle)
|
|
if len(r.Errors) == 0 {
|
|
t.Fatal("missing denied-write diagnostic")
|
|
}
|
|
c.Shutdown()
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerDenialPersistsForCurrentInstance(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(10, 150, PriorityClassNormal)
|
|
p.writable = false
|
|
c := testController(f)
|
|
c.Step()
|
|
p.writable = true
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassNormal)
|
|
c.now = func() time.Time { return time.Unix(1061, 0) }
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassNormal)
|
|
c.Shutdown()
|
|
assertPriority(t, p, PriorityClassNormal)
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerPIDReuseNeverRestoresReplacement(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
old := f.add(20, 50, PriorityClassBelowNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
old.alive = false
|
|
replacement := f.child(20, 0, 116444736000000000+1001*10000000)
|
|
replacement.info.Prio = PriorityClassBelowNormal
|
|
g.alive = false
|
|
c.Step()
|
|
assertPriority(t, replacement, PriorityClassBelowNormal)
|
|
if replacement.writes != 0 {
|
|
t.Fatal("wrote to a replacement process")
|
|
}
|
|
c.Shutdown()
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerExternalPriorityBecomesNewBaseline(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(10, 150, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
p.info.Prio = PriorityClassAboveNormal
|
|
c.Shutdown()
|
|
assertPriority(t, p, PriorityClassAboveNormal)
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerExternalChangeBeforeNextPolicyWriteIsPreservedOnExit(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(10, 150, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
p.info.Prio = PriorityClassBelowNormal
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassHigh)
|
|
c.Shutdown()
|
|
assertPriority(t, p, PriorityClassBelowNormal)
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerGameOverlayKeepsOriginalExitBaseline(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(20, 150, PriorityClassBelowNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassIdle)
|
|
g.alive = false
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassHigh)
|
|
c.Shutdown()
|
|
assertPriority(t, p, PriorityClassBelowNormal)
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerFinalSnapshotCatchesNewChild(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
parent := f.add(20, 50, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
child := f.child(30, 20, 116444736000000000+1001*10000000)
|
|
c.Shutdown()
|
|
assertPriority(t, g, PriorityClassNormal)
|
|
assertPriority(t, parent, PriorityClassNormal)
|
|
assertPriority(t, child, PriorityClassNormal)
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerDryRunHasNoWritesOrRestores(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
p := f.add(20, 50, PriorityClassBelowNormal)
|
|
c := testController(f)
|
|
c.dryRun = true
|
|
r := c.Step()
|
|
if !r.DryRun || len(r.Rows) != 2 {
|
|
t.Fatalf("bad dry-run report: %+v", r)
|
|
}
|
|
c.Shutdown()
|
|
assertPriority(t, g, PriorityClassNormal)
|
|
assertPriority(t, p, PriorityClassBelowNormal)
|
|
if g.writes+p.writes != 0 {
|
|
t.Fatal("dry-run wrote priorities")
|
|
}
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerShutdownWorksWithoutFinalSnapshot(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(10, 150, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
f.snapshotErr = true
|
|
r := c.Shutdown()
|
|
if r.Unrestored != 0 {
|
|
t.Fatal(r)
|
|
}
|
|
assertPriority(t, p, PriorityClassNormal)
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerUnrestoredFailuresReportedAndHandlesClosed(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(10, 150, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
p.writable = false
|
|
r := c.Shutdown()
|
|
if r.Unrestored != 1 {
|
|
t.Fatalf("expected one unresolved restoration, got %+v", r)
|
|
}
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerWindowsCoercionIsNotSuccessfulRestoration(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(10, 150, PriorityClassRealtime)
|
|
c := testController(f)
|
|
c.Step()
|
|
p.coerced = PriorityClassHigh
|
|
r := c.Shutdown()
|
|
if r.Unrestored != 1 {
|
|
t.Fatal("coerced REALTIME restoration was falsely reported as successful")
|
|
}
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerNoSynchronizeUsesCompletePIDMembership(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
p := f.add(20, 50, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
c.states[g.info.Key].info.Waitable = false
|
|
g.readable = false
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassIdle)
|
|
g.alive = false
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassNormal)
|
|
c.Shutdown()
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerSteadyStateDoesNotRepeatChanges(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassHigh)
|
|
p := f.add(20, 50, PriorityClassNormal)
|
|
c := testController(f)
|
|
r := c.Step()
|
|
if len(r.Rows) != 2 || !r.Rows[0].Unchanged {
|
|
t.Fatal("heavy trigger must be first, without a fictional raise")
|
|
}
|
|
writes := g.writes + p.writes
|
|
r = c.Step()
|
|
if len(r.Rows) != 0 || g.writes+p.writes != writes {
|
|
t.Fatal("repeated unchanged work")
|
|
}
|
|
c.Shutdown()
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerExternalChangeToNetUnchangedOverlayIsRespected(t *testing.T) {
|
|
f := newFake()
|
|
p := f.add(20, 150, PriorityClassIdle)
|
|
c := testController(f)
|
|
c.Step()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
p.info.RSS = 50
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassIdle)
|
|
p.info.Prio = PriorityClassBelowNormal
|
|
g.alive = false
|
|
c.Step()
|
|
assertPriority(t, p, PriorityClassBelowNormal)
|
|
c.Shutdown()
|
|
assertClosed(t, f)
|
|
}
|
|
func TestControllerRestorationRechecksOwnershipImmediatelyBeforeWrite(t *testing.T) {
|
|
for _, shutdown := range []bool{false, true} {
|
|
t.Run(map[bool]string{false: "game exit", true: "shutdown"}[shutdown], func(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
p := f.add(20, 50, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
g.alive = false
|
|
reads := 0
|
|
f.onRead = func(v *fakeProcess) {
|
|
if v == p {
|
|
reads++
|
|
if reads == 2 {
|
|
v.info.Prio = PriorityClassBelowNormal
|
|
}
|
|
}
|
|
}
|
|
if shutdown {
|
|
c.Shutdown()
|
|
} else {
|
|
c.Step()
|
|
f.onRead = nil
|
|
assertPriority(t, p, PriorityClassBelowNormal)
|
|
c.Shutdown()
|
|
}
|
|
assertPriority(t, p, PriorityClassBelowNormal)
|
|
assertClosed(t, f)
|
|
})
|
|
}
|
|
}
|
|
func TestControllerReadFailureIsBlocked(t *testing.T) {
|
|
f := newFake()
|
|
g := f.add(10, 250, PriorityClassNormal)
|
|
p := f.add(20, 50, PriorityClassNormal)
|
|
c := testController(f)
|
|
c.Step()
|
|
g.alive = false
|
|
p.failRead = true
|
|
c.Step()
|
|
r := c.Step()
|
|
if len(r.Errors) != 0 {
|
|
t.Fatal("blocked restoration repeated its error", r.Errors)
|
|
}
|
|
p.failRead = false
|
|
c.Shutdown()
|
|
assertClosed(t, f)
|
|
}
|