internal/podcount/podcount_test.go
Rama main · réplica de lectura del repositorio original.
package podcount
import (
"context"
"errors"
"fmt"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
metadatafake "k8s.io/client-go/metadata/fake"
k8stesting "k8s.io/client-go/testing"
)
func client() *metadatafake.FakeMetadataClient {
scheme := runtime.NewScheme()
err := metav1.AddMetaToScheme(scheme)
if err != nil {
panic(err)
}
return metadatafake.NewSimpleMetadataClient(scheme)
}
func pods(count int) []runtime.RawExtension {
items := make([]runtime.RawExtension, 0, count)
for i := range count {
items = append(items, runtime.RawExtension{Object: &metav1.PartialObjectMetadata{
Name: fmt.Sprintf("pod-%d", i),
Namespace: "default",
}})
}
return items
}
func answerPages(
client *metadatafake.FakeMetadataClient,
pages [][]runtime.RawExtension,
remaining *int64,
) *[]metav1ListCall {
calls := &[]metav1ListCall{}
index := 0
client.PrependReactor("list", "pods", func(action k8stesting.Action) (bool, runtime.Object, error) {
list, ok := action.(k8stesting.ListAction)
if ok {
*calls = append(*calls, metav1ListCall{fields: list.GetListRestrictions().Fields.String()})
}
page := pages[index]
out := &metav1.List{Items: page}
if index < len(pages)-1 {
out.Continue = fmt.Sprintf("page-%d", index+1)
}
if index == 0 && remaining != nil {
out.RemainingItemCount = remaining
}
index++
return true, out, nil
})
return calls
}
type metav1ListCall struct {
fields string
}
func TestARemainingEstimateWithoutAContinueTokenDoesNotInventPods(t *testing.T) {
dyn := client()
remaining := int64(41)
answerPages(dyn, [][]runtime.RawExtension{pods(1)}, &remaining)
got, err := Count(context.Background(), dyn, "")
if err != nil {
t.Fatalf("count: %v", err)
}
if got.Total != 1 {
t.Fatalf("total = %d, want the item actually returned", got.Total)
}
if !got.Complete {
t.Fatal("a list with no continuation was reported as partial")
}
}
func TestANegativeRemainingCountIsIgnored(t *testing.T) {
dyn := client()
remaining := int64(-1)
answerPages(dyn, [][]runtime.RawExtension{pods(1)}, &remaining)
got, err := Count(context.Background(), dyn, "")
if err != nil {
t.Fatalf("count: %v", err)
}
if got.Total != 1 {
t.Fatalf("total = %d, want 1", got.Total)
}
}
func TestAFilteredCountPagesToTheEndRatherThanStoppingAtOne(t *testing.T) {
dyn := client()
calls := answerPages(dyn, [][]runtime.RawExtension{
pods(500),
pods(500),
pods(7),
}, nil)
got, err := Count(context.Background(), dyn, "status.phase=Running")
if err != nil {
t.Fatalf("count: %v", err)
}
if got.Total != 1007 {
t.Fatalf("total = %d, want every page counted rather than the first one stated as the answer", got.Total)
}
if !got.Complete {
t.Fatal("a count that reached the last page said it was short")
}
if len(*calls) != 3 {
t.Fatalf("list calls = %d, want one per page", len(*calls))
}
for at, call := range *calls {
if call.fields != "status.phase=Running" {
t.Fatalf("selector on call %d = %q, want it carried through the walk", at, call.fields)
}
}
}
func TestAnUnfilteredCountWalksWhenTheServerSizesNothing(t *testing.T) {
dyn := client()
calls := answerPages(dyn, [][]runtime.RawExtension{
pods(1),
pods(500),
pods(7),
}, nil)
got, err := Count(context.Background(), dyn, "")
if err != nil {
t.Fatalf("count: %v", err)
}
if got.Total != 508 {
t.Fatalf("total = %d, want every page counted, the probe's included", got.Total)
}
if !got.Complete {
t.Fatal("a walk that reached the end was reported as partial")
}
if len(*calls) != 3 {
t.Fatalf("list calls = %d, want the probe plus two pages", len(*calls))
}
}
func TestASinglePageNeedsNoWalkAtAll(t *testing.T) {
dyn := client()
calls := answerPages(dyn, [][]runtime.RawExtension{pods(1)}, nil)
got, err := Count(context.Background(), dyn, "status.phase=Failed")
if err != nil {
t.Fatalf("count: %v", err)
}
if got.Total != 1 {
t.Fatalf("total = %d, want 1", got.Total)
}
if !got.Complete {
t.Fatal("a single page was reported as partial")
}
if len(*calls) != 1 {
t.Fatalf("list calls = %d, want just the probe", len(*calls))
}
}
func TestARefusedListIsReported(t *testing.T) {
dyn := client()
dyn.PrependReactor("list", "pods", func(k8stesting.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("pods is forbidden")
})
_, err := Count(context.Background(), dyn, "")
if err == nil {
t.Fatal("a refused list reported success")
}
}
func TestAPageThatFailsMidWalkIsReported(t *testing.T) {
dyn := client()
index := 0
dyn.PrependReactor("list", "pods", func(k8stesting.Action) (bool, runtime.Object, error) {
index++
if index == 1 {
out := &metav1.List{Items: pods(1)}
out.SetContinue("page-1")
return true, out, nil
}
return true, nil, errors.New("the continue token expired")
})
_, err := Count(context.Background(), dyn, "")
if err == nil {
t.Fatal("a failed page reported success")
}
}
func TestARepeatedContinuationTokenIsReported(t *testing.T) {
dyn := client()
dyn.PrependReactor("list", "pods", func(k8stesting.Action) (bool, runtime.Object, error) {
out := &metav1.List{Items: pods(1)}
out.SetContinue("same")
return true, out, nil
})
_, err := Count(context.Background(), dyn, "")
if !errors.Is(err, errRepeatedContinue) {
t.Fatalf("count error = %v, want the repeated token", err)
}
}
func TestAnUnfilteredProbeWalksRatherThanTrustingTheServersEstimate(t *testing.T) {
dyn := client()
remaining := int64(4000)
calls := answerPages(dyn, [][]runtime.RawExtension{
pods(1),
pods(500),
pods(7),
}, &remaining)
got, err := Count(context.Background(), dyn, "")
if err != nil {
t.Fatalf("count: %v", err)
}
if got.Total != 508 {
t.Fatalf("total = %d, want the items actually returned", got.Total)
}
if !got.Complete {
t.Fatal("a walk that reached the final page was reported as partial")
}
if len(*calls) != 3 {
t.Fatalf("list calls = %d, want the estimate verified through pagination", len(*calls))
}
}
func TestAnUnfilteredWalkStopsAtTheCeilingItAdvertises(t *testing.T) {
dyn := client()
pages := make([][]runtime.RawExtension, 0, maxPages+5)
pages = append(pages, pods(1))
for range maxPages + 4 {
pages = append(pages, pods(500))
}
answerPages(dyn, pages, nil)
got, err := Count(context.Background(), dyn, "")
if err != nil {
t.Fatalf("count: %v", err)
}
if got.Complete {
t.Fatal("a count that gave up early claimed to be complete")
}
if got.Total != Limit() {
t.Fatalf("total = %d, want exactly the %d it advertises", got.Total, Limit())
}
}