// Copyright 2025 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 cgrouptest provides best-effort helpers for running tests inside a
// cgroup.
package cgrouptest

import (
	"fmt"
	"internal/runtime/cgroup"
	"os"
	"path/filepath"
	"slices"
	"strconv"
	"strings"
	"syscall"
	"testing"
)

type CgroupV2 struct {
	orig string
	path string
}

func (c *CgroupV2) Path() string {
	return c.path
}

// Path to cpu.max.
func (c *CgroupV2) CPUMaxPath() string {
	return filepath.Join(c.path, "cpu.max")
}

// Set cpu.max. Pass -1 for quota to disable the limit.
func (c *CgroupV2) SetCPUMax(quota, period int64) error {
	q := "max"
	if quota >= 0 {
		q = strconv.FormatInt(quota, 10)
	}
	buf := fmt.Sprintf("%s %d", q, period)
	return os.WriteFile(c.CPUMaxPath(), []byte(buf), 0)
}

// InCgroupV2 creates a new v2 cgroup, migrates the current process into it,
// and then calls fn. When fn returns, the current process is migrated back to
// the original cgroup and the new cgroup is destroyed.
//
// If a new cgroup cannot be created, the test is skipped.
//
// This must not be used in parallel tests, as it affects the entire process.
func InCgroupV2(t *testing.T, fn func(*CgroupV2)) {
	mount, rel := findCurrent(t)
	parent := findOwnedParent(t, mount, rel)
	orig := filepath.Join(mount, rel)

	// Make sure the parent allows children to control cpu.
	b, err := os.ReadFile(filepath.Join(parent, "cgroup.subtree_control"))
	if err != nil {
		t.Skipf("unable to read cgroup.subtree_control: %v", err)
	}
	if !slices.Contains(strings.Fields(string(b)), "cpu") {
		// N.B. We should have permission to add cpu to
		// subtree_control, but it seems like a bad idea to change this
		// on a high-level cgroup that probably has lots of existing
		// children.
		t.Skipf("Parent cgroup %s does not allow children to control cpu, only %q", parent, string(b))
	}

	path, err := os.MkdirTemp(parent, "go-cgrouptest")
	if err != nil {
		t.Skipf("unable to create cgroup directory: %v", err)
	}
	// Important: defer cleanups so they run even in the event of panic.
	//
	// TODO(prattmic): Consider running everything in a subprocess just so
	// we can clean up if it throws or otherwise doesn't run the defers.
	defer func() {
		if err := os.Remove(path); err != nil {
			// Not much we can do, but at least inform of the
			// problem.
			t.Errorf("Error removing cgroup directory: %v", err)
		}
	}()

	migrateTo(t, path)
	defer migrateTo(t, orig)

	c := &CgroupV2{
		orig: orig,
		path: path,
	}
	fn(c)
}

// Returns the mount and relative directory of the current cgroup the process
// is in.
func findCurrent(t *testing.T) (string, string) {
	// Find the path to our current CPU cgroup. Currently this package is
	// only used for CPU cgroup testing, so the distinction of different
	// controllers doesn't matter.
	var scratch [cgroup.ParseSize]byte
	buf := make([]byte, cgroup.PathSize)
	n, err := cgroup.FindCPUMountPoint(buf, scratch[:])
	if err != nil {
		t.Skipf("cgroup: unable to find current cgroup mount: %v", err)
	}
	mount := string(buf[:n])

	n, ver, err := cgroup.FindCPURelativePath(buf, scratch[:])
	if err != nil {
		t.Skipf("cgroup: unable to find current cgroup path: %v", err)
	}
	if ver != cgroup.V2 {
		t.Skipf("cgroup: running on cgroup v%d want v2", ver)
	}
	rel := string(buf[1:n])       // The returned path always starts with /, skip it.
	rel = filepath.Join(".", rel) // Make sure this isn't empty string at root.
	return mount, rel
}

// Returns a parent directory in which we can create our own cgroup subdirectory.
func findOwnedParent(t *testing.T, mount, rel string) string {
	// There are many ways cgroups may be set up on a system. We don't try
	// to cover all of them, just common ones.
	//
	// To start with, systemd:
	//
	// Our test process is likely running inside a user session, in which
	// case we are likely inside a cgroup that looks something like:
	//
	//   /sys/fs/cgroup/user.slice/user-1234.slice/user@1234.service/vte-spawn-1.scope/
	//
	// Possibly with additional slice layers between user@1234.service and
	// the leaf scope.
	//
	// On new enough kernel and systemd versions (exact versions unknown),
	// full unprivileged control of the user's cgroups is permitted
	// directly via the cgroup filesystem. Specifically, the
	// user@1234.service directory is owned by the user, as are all
	// subdirectories.

	// We want to create our own subdirectory that we can migrate into and
	// then manipulate at will. It is tempting to create a new subdirectory
	// inside the current cgroup we are already in, however that will likey
	// not work. cgroup v2 only allows processes to be in leaf cgroups. Our
	// current cgroup likely contains multiple processes (at least this one
	// and the cmd/go test runner). If we make a subdirectory and try to
	// move our process into that cgroup, then the subdirectory and parent
	// would both contain processes. Linux won't allow us to do that [1].
	//
	// Instead, we will simply walk up to the highest directory that our
	// user owns and create our new subdirectory. Since that directory
	// already has a bunch of subdirectories, it must not directly contain
	// and processes.
	//
	// (This would fall apart if we already in the highest directory we
	// own, such as if there was simply a single cgroup for the entire
	// user. Luckily systemd at least does not do this.)
	//
	// [1] Minor technicality: By default a new subdirectory has no cgroup
	// controller (they must be explicitly enabled in the parent's
	// cgroup.subtree_control). Linux will allow moving processes into a
	// subdirectory that has no controllers while there are still processes
	// in the parent, but it won't allow adding controller until the parent
	// is empty. As far as I tell, the only purpose of this is to allow
	// reorganizing processes into a new set of subdirectories and then
	// adding controllers once done.
	root, err := os.OpenRoot(mount)
	if err != nil {
		t.Fatalf("error opening cgroup mount root: %v", err)
	}

	uid := os.Getuid()
	var prev string
	for rel != "." {
		fi, err := root.Stat(rel)
		if err != nil {
			t.Fatalf("error stating cgroup path: %v", err)
		}

		st := fi.Sys().(*syscall.Stat_t)
		if int(st.Uid) != uid {
			// Stop at first directory we don't own.
			break
		}

		prev = rel
		rel = filepath.Join(rel, "..")
	}

	if prev == "" {
		t.Skipf("No parent cgroup owned by UID %d", uid)
	}

	// We actually want the last directory where we were the owner.
	return filepath.Join(mount, prev)
}

// Migrate the current process to the cgroup directory dst.
func migrateTo(t *testing.T, dst string) {
	pid := []byte(strconv.FormatInt(int64(os.Getpid()), 10))
	if err := os.WriteFile(filepath.Join(dst, "cgroup.procs"), pid, 0); err != nil {
		t.Skipf("Unable to migrate into %s: %v", dst, err)
	}
}
