123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- /*
- Copyright 2017 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package cpumanager
- import (
- "reflect"
- "testing"
- "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/topology"
- "k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
- )
- func TestCPUAccumulatorFreeSockets(t *testing.T) {
- testCases := []struct {
- description string
- topo *topology.CPUTopology
- availableCPUs cpuset.CPUSet
- expect []int
- }{
- {
- "single socket HT, 1 socket free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- []int{0},
- },
- {
- "single socket HT, 0 sockets free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7),
- []int{},
- },
- {
- "dual socket HT, 2 sockets free",
- topoDualSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- []int{0, 1},
- },
- {
- "dual socket HT, 1 socket free",
- topoDualSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11),
- []int{1},
- },
- {
- "dual socket HT, 0 sockets free",
- topoDualSocketHT,
- cpuset.NewCPUSet(0, 2, 3, 4, 5, 6, 7, 8, 9, 11),
- []int{},
- },
- }
- for _, tc := range testCases {
- acc := newCPUAccumulator(tc.topo, tc.availableCPUs, 0)
- result := acc.freeSockets()
- if !reflect.DeepEqual(result, tc.expect) {
- t.Errorf("[%s] expected %v to equal %v", tc.description, result, tc.expect)
- }
- }
- }
- func TestCPUAccumulatorFreeCores(t *testing.T) {
- testCases := []struct {
- description string
- topo *topology.CPUTopology
- availableCPUs cpuset.CPUSet
- expect []int
- }{
- {
- "single socket HT, 4 cores free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- []int{0, 1, 2, 3},
- },
- {
- "single socket HT, 3 cores free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 4, 5, 6),
- []int{0, 1, 2},
- },
- {
- "single socket HT, 3 cores free (1 partially consumed)",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6),
- []int{0, 1, 2},
- },
- {
- "single socket HT, 0 cores free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(),
- []int{},
- },
- {
- "single socket HT, 0 cores free (4 partially consumed)",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3),
- []int{},
- },
- {
- "dual socket HT, 6 cores free",
- topoDualSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- []int{0, 2, 4, 1, 3, 5},
- },
- {
- "dual socket HT, 5 cores free (1 consumed from socket 0)",
- topoDualSocketHT,
- cpuset.NewCPUSet(2, 1, 3, 4, 5, 7, 8, 9, 10, 11),
- []int{2, 4, 1, 3, 5},
- },
- {
- "dual socket HT, 4 cores free (1 consumed from each socket)",
- topoDualSocketHT,
- cpuset.NewCPUSet(2, 3, 4, 5, 8, 9, 10, 11),
- []int{2, 4, 3, 5},
- },
- }
- for _, tc := range testCases {
- acc := newCPUAccumulator(tc.topo, tc.availableCPUs, 0)
- result := acc.freeCores()
- if !reflect.DeepEqual(result, tc.expect) {
- t.Errorf("[%s] expected %v to equal %v", tc.description, result, tc.expect)
- }
- }
- }
- func TestCPUAccumulatorFreeCPUs(t *testing.T) {
- testCases := []struct {
- description string
- topo *topology.CPUTopology
- availableCPUs cpuset.CPUSet
- expect []int
- }{
- {
- "single socket HT, 8 cpus free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- []int{0, 4, 1, 5, 2, 6, 3, 7},
- },
- {
- "single socket HT, 5 cpus free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(3, 4, 5, 6, 7),
- []int{4, 5, 6, 3, 7},
- },
- {
- "dual socket HT, 12 cpus free",
- topoDualSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- []int{0, 6, 2, 8, 4, 10, 1, 7, 3, 9, 5, 11},
- },
- {
- "dual socket HT, 11 cpus free",
- topoDualSocketHT,
- cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- []int{6, 2, 8, 4, 10, 1, 7, 3, 9, 5, 11},
- },
- {
- "dual socket HT, 10 cpus free",
- topoDualSocketHT,
- cpuset.NewCPUSet(1, 2, 3, 4, 5, 7, 8, 9, 10, 11),
- []int{2, 8, 4, 10, 1, 7, 3, 9, 5, 11},
- },
- }
- for _, tc := range testCases {
- acc := newCPUAccumulator(tc.topo, tc.availableCPUs, 0)
- result := acc.freeCPUs()
- if !reflect.DeepEqual(result, tc.expect) {
- t.Errorf("[%s] expected %v to equal %v", tc.description, result, tc.expect)
- }
- }
- }
- func TestCPUAccumulatorTake(t *testing.T) {
- testCases := []struct {
- description string
- topo *topology.CPUTopology
- availableCPUs cpuset.CPUSet
- takeCPUs []cpuset.CPUSet
- numCPUs int
- expectSatisfied bool
- expectFailed bool
- }{
- {
- "take 0 cpus from a single socket HT, require 1",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- []cpuset.CPUSet{cpuset.NewCPUSet()},
- 1,
- false,
- false,
- },
- {
- "take 0 cpus from a single socket HT, require 1, none available",
- topoSingleSocketHT,
- cpuset.NewCPUSet(),
- []cpuset.CPUSet{cpuset.NewCPUSet()},
- 1,
- false,
- true,
- },
- {
- "take 1 cpu from a single socket HT, require 1",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- []cpuset.CPUSet{cpuset.NewCPUSet(0)},
- 1,
- true,
- false,
- },
- {
- "take 1 cpu from a single socket HT, require 2",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- []cpuset.CPUSet{cpuset.NewCPUSet(0)},
- 2,
- false,
- false,
- },
- {
- "take 2 cpu from a single socket HT, require 4, expect failed",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2),
- []cpuset.CPUSet{cpuset.NewCPUSet(0), cpuset.NewCPUSet(1)},
- 4,
- false,
- true,
- },
- {
- "take all cpus one at a time from a single socket HT, require 8",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- []cpuset.CPUSet{
- cpuset.NewCPUSet(0),
- cpuset.NewCPUSet(1),
- cpuset.NewCPUSet(2),
- cpuset.NewCPUSet(3),
- cpuset.NewCPUSet(4),
- cpuset.NewCPUSet(5),
- cpuset.NewCPUSet(6),
- cpuset.NewCPUSet(7),
- },
- 8,
- true,
- false,
- },
- }
- for _, tc := range testCases {
- acc := newCPUAccumulator(tc.topo, tc.availableCPUs, tc.numCPUs)
- totalTaken := 0
- for _, cpus := range tc.takeCPUs {
- acc.take(cpus)
- totalTaken += cpus.Size()
- }
- if tc.expectSatisfied != acc.isSatisfied() {
- t.Errorf("[%s] expected acc.isSatisfied() to be %t", tc.description, tc.expectSatisfied)
- }
- if tc.expectFailed != acc.isFailed() {
- t.Errorf("[%s] expected acc.isFailed() to be %t", tc.description, tc.expectFailed)
- }
- for _, cpus := range tc.takeCPUs {
- availableCPUs := acc.details.CPUs()
- if cpus.Intersection(availableCPUs).Size() > 0 {
- t.Errorf("[%s] expected intersection of taken cpus [%s] and acc.details.CPUs() [%s] to be empty", tc.description, cpus, availableCPUs)
- }
- if !cpus.IsSubsetOf(acc.result) {
- t.Errorf("[%s] expected [%s] to be a subset of acc.result [%s]", tc.description, cpus, acc.result)
- }
- }
- expNumCPUsNeeded := tc.numCPUs - totalTaken
- if acc.numCPUsNeeded != expNumCPUsNeeded {
- t.Errorf("[%s] expected acc.numCPUsNeeded to be %d (got %d)", tc.description, expNumCPUsNeeded, acc.numCPUsNeeded)
- }
- }
- }
- func TestTakeByTopology(t *testing.T) {
- testCases := []struct {
- description string
- topo *topology.CPUTopology
- availableCPUs cpuset.CPUSet
- numCPUs int
- expErr string
- expResult cpuset.CPUSet
- }{
- {
- "take more cpus than are available from single socket with HT",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 2, 4, 6),
- 5,
- "not enough cpus available to satisfy request",
- cpuset.NewCPUSet(),
- },
- {
- "take zero cpus from single socket with HT",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- 0,
- "",
- cpuset.NewCPUSet(),
- },
- {
- "take one cpu from single socket with HT",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- 1,
- "",
- cpuset.NewCPUSet(0),
- },
- {
- "take one cpu from single socket with HT, some cpus are taken",
- topoSingleSocketHT,
- cpuset.NewCPUSet(1, 3, 5, 6, 7),
- 1,
- "",
- cpuset.NewCPUSet(6),
- },
- {
- "take two cpus from single socket with HT",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- 2,
- "",
- cpuset.NewCPUSet(0, 4),
- },
- {
- "take all cpus from single socket with HT",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- 8,
- "",
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- },
- {
- "take two cpus from single socket with HT, only one core totally free",
- topoSingleSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 6),
- 2,
- "",
- cpuset.NewCPUSet(2, 6),
- },
- {
- "take one cpu from dual socket with HT - core from Socket 0",
- topoDualSocketHT,
- cpuset.NewCPUSet(1, 2, 3, 4, 5, 7, 8, 9, 10, 11),
- 1,
- "",
- cpuset.NewCPUSet(2),
- },
- {
- "take a socket of cpus from dual socket with HT",
- topoDualSocketHT,
- cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- 6,
- "",
- cpuset.NewCPUSet(0, 2, 4, 6, 8, 10),
- },
- }
- for _, tc := range testCases {
- result, err := takeByTopology(tc.topo, tc.availableCPUs, tc.numCPUs)
- if tc.expErr != "" && err.Error() != tc.expErr {
- t.Errorf("expected error to be [%v] but it was [%v] in test \"%s\"", tc.expErr, err, tc.description)
- }
- if !result.Equals(tc.expResult) {
- t.Errorf("expected result [%s] to equal [%s] in test \"%s\"", result, tc.expResult, tc.description)
- }
- }
- }
|