* Initial work on rapl-daemon. Initial server set up. API to read max power per zone and API to write new power cap have both been written. * Removing python script since this has been ported to go code now. * Adding test for happy path retrieving max power. * Change some data types around to avoid too much conversion. * Add happy path test for cap zone * Removing uncessary print statement. * Change cap node to use a temporary setup. * Renaming arguments to be more descriptive. * Changing todo message. * Changing test structure to only set up mock subsystem once and allowing functions to test on it later. * Adding some more coverage for unhappy paths and fixing some values to reflect they are no longer floats. * Keeping the old script around as it should be removed in a different PR. * Delegating percentage check to capNode function. * Fixing typo. * Fixing typos. * Changing shortWindow to longWindow as constraint_0 actually points to the long window. * Renaming variable in test. * capping funciton now returns which zones were sucessfully capped and which zones could not be capped. This information is now returned to the caller of the HTTP api.
101 lines
2.2 KiB
Go
101 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var raplDir string
|
|
|
|
const maxWattage uint64 = 1500000
|
|
|
|
func TestMain(m *testing.M) {
|
|
var err error
|
|
raplDir, err = ioutil.TempDir("", raplPrefixCPU)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
defer os.RemoveAll(raplDir)
|
|
|
|
// Create temporary directory that mocks powercap subsytem
|
|
zonePath := filepath.Join(raplDir, raplPrefixCPU+":0")
|
|
err = os.Mkdir(zonePath, 755)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
initialWatts := strconv.FormatUint(maxWattage, 10)
|
|
|
|
err = ioutil.WriteFile(filepath.Join(zonePath, maxPowerFileLongWindow), []byte(initialWatts), 0444)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
err = ioutil.WriteFile(filepath.Join(zonePath, powerLimitFileLongWindow), []byte(initialWatts), 0644)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
// TODO(rdelvalle): Add tests where capping fails
|
|
func TestCapNode(t *testing.T) {
|
|
capped, failed, err := capNode(raplDir, 95)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, capped, 1)
|
|
assert.Nil(t, failed)
|
|
|
|
t.Run("bad-percentage", func(t *testing.T) {
|
|
capped, failed, err := capNode(raplDir, 1000)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, capped)
|
|
assert.Nil(t, failed)
|
|
})
|
|
|
|
t.Run("zero-percent", func(t *testing.T) {
|
|
capped, failed, err := capNode(raplDir, 0)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, capped)
|
|
assert.Nil(t, failed)
|
|
})
|
|
}
|
|
|
|
func TestMaxPower(t *testing.T) {
|
|
maxFile := filepath.Join(raplDir, raplPrefixCPU+":0", maxPowerFileLongWindow)
|
|
|
|
maxWatts, err := maxPower(maxFile)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, maxWattage, maxWatts)
|
|
|
|
t.Run("name-does-not-exist", func(t *testing.T) {
|
|
_, err := maxPower("madeupname")
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestCapZone(t *testing.T) {
|
|
const percentage float64 = .50
|
|
|
|
powercap := uint64(math.Ceil(float64(maxWattage) * percentage))
|
|
limitFile := filepath.Join(raplDir, raplPrefixCPU+":0", powerLimitFileLongWindow)
|
|
err := capZone(limitFile, powercap)
|
|
assert.NoError(t, err)
|
|
|
|
newCap, err := currentCap(limitFile)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, powercap, newCap)
|
|
|
|
t.Run("name-does-not-exist", func(t *testing.T) {
|
|
err := capZone("madeupname", powercap)
|
|
assert.Error(t, err)
|
|
})
|
|
}
|