mirror of https://github.com/knative/pkg.git
Switch *testing.T uses to equivalent interface + structured logging (#935)
Working to introduce structured logging to our tests. See #907 This work allows these test functions to be called by objects other than *testing.T. The t.Error() calls are made compatible with structured logging (wrapping Zap sugared logger calls) or code using testing.T.
This commit is contained in:
parent
f890690397
commit
9d8b936ca0
|
|
@ -17,11 +17,11 @@ package testing
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"knative.dev/pkg/apis"
|
||||
duckv1b1 "knative.dev/pkg/apis/duck/v1beta1"
|
||||
"knative.dev/pkg/test"
|
||||
)
|
||||
|
||||
// CheckCondition checks if condition `c` on `cc` has value `cs`.
|
||||
|
|
@ -39,7 +39,7 @@ func CheckCondition(s *duckv1b1.Status, c apis.ConditionType, cs corev1.Conditio
|
|||
|
||||
// CheckConditionOngoing checks if the condition is in state `Unknown`.
|
||||
// DEPRECATED: Use versioned test helper
|
||||
func CheckConditionOngoing(s *duckv1b1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionOngoing(s *duckv1b1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionUnknown); err != nil {
|
||||
t.Error(err)
|
||||
|
|
@ -48,7 +48,7 @@ func CheckConditionOngoing(s *duckv1b1.Status, c apis.ConditionType, t *testing.
|
|||
|
||||
// CheckConditionFailed checks if the condition is in state `False`.
|
||||
// DEPRECATED: Use versioned test helper
|
||||
func CheckConditionFailed(s *duckv1b1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionFailed(s *duckv1b1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionFalse); err != nil {
|
||||
t.Error(err)
|
||||
|
|
@ -57,7 +57,7 @@ func CheckConditionFailed(s *duckv1b1.Status, c apis.ConditionType, t *testing.T
|
|||
|
||||
// CheckConditionSucceeded checks if the condition is in state `True`.
|
||||
// DEPRECATED: Use versioned test helper
|
||||
func CheckConditionSucceeded(s *duckv1b1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionSucceeded(s *duckv1b1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionTrue); err != nil {
|
||||
t.Error(err)
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ package v1
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"knative.dev/pkg/apis"
|
||||
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||
"knative.dev/pkg/test"
|
||||
)
|
||||
|
||||
// CheckCondition checks if condition `c` on `cc` has value `cs`.
|
||||
|
|
@ -37,7 +37,7 @@ func CheckCondition(s *duckv1.Status, c apis.ConditionType, cs corev1.ConditionS
|
|||
}
|
||||
|
||||
// CheckConditionOngoing checks if the condition is in state `Unknown`.
|
||||
func CheckConditionOngoing(s *duckv1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionOngoing(s *duckv1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionUnknown); err != nil {
|
||||
t.Error(err)
|
||||
|
|
@ -45,7 +45,7 @@ func CheckConditionOngoing(s *duckv1.Status, c apis.ConditionType, t *testing.T)
|
|||
}
|
||||
|
||||
// CheckConditionFailed checks if the condition is in state `False`.
|
||||
func CheckConditionFailed(s *duckv1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionFailed(s *duckv1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionFalse); err != nil {
|
||||
t.Error(err)
|
||||
|
|
@ -53,7 +53,7 @@ func CheckConditionFailed(s *duckv1.Status, c apis.ConditionType, t *testing.T)
|
|||
}
|
||||
|
||||
// CheckConditionSucceeded checks if the condition is in state `True`.
|
||||
func CheckConditionSucceeded(s *duckv1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionSucceeded(s *duckv1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionTrue); err != nil {
|
||||
t.Error(err)
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ package testing
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"knative.dev/pkg/apis"
|
||||
duckv1b1 "knative.dev/pkg/apis/duck/v1beta1"
|
||||
"knative.dev/pkg/test"
|
||||
)
|
||||
|
||||
// CheckCondition checks if condition `c` on `cc` has value `cs`.
|
||||
|
|
@ -37,7 +37,7 @@ func CheckCondition(s *duckv1b1.Status, c apis.ConditionType, cs corev1.Conditio
|
|||
}
|
||||
|
||||
// CheckConditionOngoing checks if the condition is in state `Unknown`.
|
||||
func CheckConditionOngoing(s *duckv1b1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionOngoing(s *duckv1b1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionUnknown); err != nil {
|
||||
t.Error(err)
|
||||
|
|
@ -45,7 +45,7 @@ func CheckConditionOngoing(s *duckv1b1.Status, c apis.ConditionType, t *testing.
|
|||
}
|
||||
|
||||
// CheckConditionFailed checks if the condition is in state `False`.
|
||||
func CheckConditionFailed(s *duckv1b1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionFailed(s *duckv1b1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionFalse); err != nil {
|
||||
t.Error(err)
|
||||
|
|
@ -53,7 +53,7 @@ func CheckConditionFailed(s *duckv1b1.Status, c apis.ConditionType, t *testing.T
|
|||
}
|
||||
|
||||
// CheckConditionSucceeded checks if the condition is in state `True`.
|
||||
func CheckConditionSucceeded(s *duckv1b1.Status, c apis.ConditionType, t *testing.T) {
|
||||
func CheckConditionSucceeded(s *duckv1b1.Status, c apis.ConditionType, t test.T) {
|
||||
t.Helper()
|
||||
if err := CheckCondition(s, c, corev1.ConditionTrue); err != nil {
|
||||
t.Error(err)
|
||||
|
|
|
|||
|
|
@ -16,51 +16,52 @@ limitations under the License.
|
|||
package metricstest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"reflect"
|
||||
|
||||
"go.opencensus.io/stats/view"
|
||||
"knative.dev/pkg/test"
|
||||
)
|
||||
|
||||
// CheckStatsReported checks that there is a view registered with the given name for each string in names,
|
||||
// and that each view has at least one record.
|
||||
func CheckStatsReported(t *testing.T, names ...string) {
|
||||
func CheckStatsReported(t test.T, names ...string) {
|
||||
t.Helper()
|
||||
for _, name := range names {
|
||||
d, err := view.RetrieveData(name)
|
||||
if err != nil {
|
||||
t.Errorf("For metric %s: Reporter.Report() error = %v", name, err)
|
||||
t.Error("For metric, Reporter.Report() error", "metric", name, "error", err)
|
||||
}
|
||||
if len(d) < 1 {
|
||||
t.Errorf("For metric %s: No data reported when data was expected, view data is empty.", name)
|
||||
t.Error("For metric, no data reported when data was expected, view data is empty.", "metric", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckStatsNotReported checks that there are no records for any views that a name matching a string in names.
|
||||
// Names that do not match registered views are considered not reported.
|
||||
func CheckStatsNotReported(t *testing.T, names ...string) {
|
||||
func CheckStatsNotReported(t test.T, names ...string) {
|
||||
t.Helper()
|
||||
for _, name := range names {
|
||||
d, err := view.RetrieveData(name)
|
||||
// err == nil means a valid stat exists matching "name"
|
||||
// len(d) > 0 means a component recorded metrics for that stat
|
||||
if err == nil && len(d) > 0 {
|
||||
t.Errorf("For metric %s: Unexpected data reported when no data was expected. Reporter len(d) = %d", name, len(d))
|
||||
t.Error("For metric, unexpected data reported when no data was expected.", "metric", name, "Reporter len(d)", len(d))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckCountData checks the view with a name matching string name to verify that the CountData stats
|
||||
// reported are tagged with the tags in wantTags and that wantValue matches reported count.
|
||||
func CheckCountData(t *testing.T, name string, wantTags map[string]string, wantValue int64) {
|
||||
func CheckCountData(t test.T, name string, wantTags map[string]string, wantValue int64) {
|
||||
t.Helper()
|
||||
if row := checkExactlyOneRow(t, name); row != nil {
|
||||
checkRowTags(t, row, name, wantTags)
|
||||
|
||||
if s, ok := row.Data.(*view.CountData); !ok {
|
||||
t.Errorf("%s: got %T, want CountData", name, row.Data)
|
||||
t.Error("want CountData", "metric", name, "got", reflect.TypeOf(row.Data))
|
||||
} else if s.Value != wantValue {
|
||||
t.Errorf("For metric %s: value = %v, want: %d", name, s.Value, wantValue)
|
||||
t.Error("Wrong value", "metric", name, "value", s.Value, "want", wantValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,22 +69,22 @@ func CheckCountData(t *testing.T, name string, wantTags map[string]string, wantV
|
|||
// CheckDistributionData checks the view with a name matching string name to verify that the DistributionData stats reported
|
||||
// are tagged with the tags in wantTags and that expectedCount number of records were reported.
|
||||
// It also checks that expectedMin and expectedMax match the minimum and maximum reported values, respectively.
|
||||
func CheckDistributionData(t *testing.T, name string, wantTags map[string]string, expectedCount int64, expectedMin float64, expectedMax float64) {
|
||||
func CheckDistributionData(t test.T, name string, wantTags map[string]string, expectedCount int64, expectedMin float64, expectedMax float64) {
|
||||
t.Helper()
|
||||
if row := checkExactlyOneRow(t, name); row != nil {
|
||||
checkRowTags(t, row, name, wantTags)
|
||||
|
||||
if s, ok := row.Data.(*view.DistributionData); !ok {
|
||||
t.Errorf("%s: got %T, want DistributionData", name, row.Data)
|
||||
t.Error("want DistributionData", "metric", name, "got", reflect.TypeOf(row.Data))
|
||||
} else {
|
||||
if s.Count != expectedCount {
|
||||
t.Errorf("For metric %s: reporter count = %d, want = %d", name, s.Count, expectedCount)
|
||||
t.Error("reporter count wrong", "metric", name, "got", s.Count, "want", expectedCount)
|
||||
}
|
||||
if s.Min != expectedMin {
|
||||
t.Errorf("For metric %s: reporter count = %f, want = %f", name, s.Min, expectedMin)
|
||||
t.Error("reporter count wrong", "metric", name, "got", s.Min, "want", expectedMin)
|
||||
}
|
||||
if s.Max != expectedMax {
|
||||
t.Errorf("For metric %s: reporter count = %f, want = %f", name, s.Max, expectedMax)
|
||||
t.Error("reporter count wrong", "metric", name, "got", s.Max, "want", expectedMax)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -91,30 +92,30 @@ func CheckDistributionData(t *testing.T, name string, wantTags map[string]string
|
|||
|
||||
// CheckLastValueData checks the view with a name matching string name to verify that the LastValueData stats
|
||||
// reported are tagged with the tags in wantTags and that wantValue matches reported last value.
|
||||
func CheckLastValueData(t *testing.T, name string, wantTags map[string]string, wantValue float64) {
|
||||
func CheckLastValueData(t test.T, name string, wantTags map[string]string, wantValue float64) {
|
||||
t.Helper()
|
||||
if row := checkExactlyOneRow(t, name); row != nil {
|
||||
checkRowTags(t, row, name, wantTags)
|
||||
|
||||
if s, ok := row.Data.(*view.LastValueData); !ok {
|
||||
t.Errorf("%s: got %T, want LastValueData", name, row.Data)
|
||||
t.Error("want LastValueData", "metric", name, "got", reflect.TypeOf(row.Data))
|
||||
} else if s.Value != wantValue {
|
||||
t.Errorf("For metric %s: Reporter.Report() expected %v got %v", name, s.Value, wantValue)
|
||||
t.Error("Reporter.Report() wrong value", "metric", name, "got", s.Value, "want", wantValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckSumData checks the view with a name matching string name to verify that the SumData stats
|
||||
// reported are tagged with the tags in wantTags and that wantValue matches the reported sum.
|
||||
func CheckSumData(t *testing.T, name string, wantTags map[string]string, wantValue float64) {
|
||||
func CheckSumData(t test.T, name string, wantTags map[string]string, wantValue float64) {
|
||||
t.Helper()
|
||||
if row := checkExactlyOneRow(t, name); row != nil {
|
||||
checkRowTags(t, row, name, wantTags)
|
||||
|
||||
if s, ok := row.Data.(*view.SumData); !ok {
|
||||
t.Errorf("%s: got %T, want SumData", name, row.Data)
|
||||
t.Error("Wrong type", "metric", name, "got", reflect.TypeOf(row.Data), "want", "SumData")
|
||||
} else if s.Value != wantValue {
|
||||
t.Errorf("For metric %s: value = %v, want: %v", name, s.Value, wantValue)
|
||||
t.Error("Wrong sumdata", "metric", name, "got", s.Value, "want", wantValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -134,32 +135,32 @@ func Unregister(names ...string) {
|
|||
}
|
||||
}
|
||||
|
||||
func checkExactlyOneRow(t *testing.T, name string) *view.Row {
|
||||
func checkExactlyOneRow(t test.T, name string) *view.Row {
|
||||
t.Helper()
|
||||
d, err := view.RetrieveData(name)
|
||||
if err != nil {
|
||||
t.Errorf("For metric %s: Reporter.Report() error = %v", name, err)
|
||||
t.Error("Reporter.Report() error", "metric", name, "error", err)
|
||||
return nil
|
||||
}
|
||||
if len(d) != 1 {
|
||||
t.Errorf("For metric %s: Reporter.Report() len(d)=%v, want 1", name, len(d))
|
||||
t.Error("Reporter.Report() wrong length", "metric", name, "got", len(d), "want", 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
return d[0]
|
||||
}
|
||||
|
||||
func checkRowTags(t *testing.T, row *view.Row, name string, wantTags map[string]string) {
|
||||
func checkRowTags(t test.T, row *view.Row, name string, wantTags map[string]string) {
|
||||
t.Helper()
|
||||
if wantlen, gotlen := len(wantTags), len(row.Tags); gotlen != wantlen {
|
||||
t.Errorf("For metric %s: Reporter got %v tags while want %v", name, gotlen, wantlen)
|
||||
t.Error("Reporter got wrong number of tags", "metric", name, "got", gotlen, "want", wantlen)
|
||||
}
|
||||
for _, got := range row.Tags {
|
||||
n := got.Key.Name()
|
||||
if want, ok := wantTags[n]; !ok {
|
||||
t.Errorf("For metric %s: Reporter got an extra tag %v: %v", name, n, got.Value)
|
||||
t.Error("Reporter got an extra tag", "metric", name, "gotName", n, "gotValue", got.Value)
|
||||
} else if got.Value != want {
|
||||
t.Errorf("For metric %s: Reporter expected a different tag value for key: %s, got: %s, want: %s", name, n, got.Value, want)
|
||||
t.Error("Reporter expected a different tag value for key", "metric", name, "key", n, "got", got.Value, "want", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ import (
|
|||
"log"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"knative.dev/pkg/test"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -42,12 +43,12 @@ func init() {
|
|||
}
|
||||
|
||||
// ObjectPrefixForTest returns the name prefix for this test's random names.
|
||||
func ObjectPrefixForTest(t *testing.T) string {
|
||||
func ObjectPrefixForTest(t test.T) string {
|
||||
return MakeK8sNamePrefix(strings.TrimPrefix(t.Name(), testNamePrefix))
|
||||
}
|
||||
|
||||
// ObjectNameForTest generates a random object name based on the test name.
|
||||
func ObjectNameForTest(t *testing.T) string {
|
||||
func ObjectNameForTest(t test.T) string {
|
||||
return AppendRandomString(ObjectPrefixForTest(t))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ package logstream
|
|||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"knative.dev/pkg/system"
|
||||
"knative.dev/pkg/test"
|
||||
)
|
||||
|
||||
// Canceler is the type of a function returned when a logstream is started to be
|
||||
|
|
@ -30,12 +30,12 @@ type Canceler func()
|
|||
// Start begins streaming the logs from system components with a `key:` matching
|
||||
// `test.ObjectNameForTest(t)` to `t.Log`. It returns a Canceler, which must
|
||||
// be called before the test completes.
|
||||
func Start(t *testing.T) Canceler {
|
||||
func Start(t test.TLegacy) Canceler {
|
||||
return stream.Start(t)
|
||||
}
|
||||
|
||||
type streamer interface {
|
||||
Start(t *testing.T) Canceler
|
||||
Start(t test.TLegacy) Canceler
|
||||
}
|
||||
|
||||
var stream streamer
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
|
@ -50,18 +49,18 @@ var _ streamer = (*kubelogs)(nil)
|
|||
// timeFormat defines a simple timestamp with millisecond granularity
|
||||
const timeFormat = "15:04:05.000"
|
||||
|
||||
func (k *kubelogs) init(t *testing.T) {
|
||||
func (k *kubelogs) init(t test.TLegacy) {
|
||||
k.keys = make(map[string]logger)
|
||||
|
||||
kc, err := test.NewKubeClient(test.Flags.Kubeconfig, test.Flags.Cluster)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading client config: %v", err)
|
||||
t.Error("Error loading client config", "error", err)
|
||||
}
|
||||
|
||||
// List the pods in the given namespace.
|
||||
pl, err := kc.Kube.CoreV1().Pods(k.namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("Error listing pods: %v", err)
|
||||
t.Error("Error listing pods", "error", err)
|
||||
}
|
||||
|
||||
eg := errgroup.Group{}
|
||||
|
|
@ -160,7 +159,7 @@ func (k *kubelogs) handleLine(l string) {
|
|||
}
|
||||
|
||||
// Start implements streamer
|
||||
func (k *kubelogs) Start(t *testing.T) Canceler {
|
||||
func (k *kubelogs) Start(t test.TLegacy) Canceler {
|
||||
k.once.Do(func() { k.init(t) })
|
||||
|
||||
name := helpers.ObjectPrefixForTest(t)
|
||||
|
|
@ -177,7 +176,7 @@ func (k *kubelogs) Start(t *testing.T) Canceler {
|
|||
delete(k.keys, name)
|
||||
|
||||
if k.err != nil {
|
||||
t.Errorf("error during logstream: %v", k.err)
|
||||
t.Error("error during logstream", "error", k.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,15 +16,13 @@ limitations under the License.
|
|||
|
||||
package logstream
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
import "knative.dev/pkg/test"
|
||||
|
||||
type null struct{}
|
||||
|
||||
var _ streamer = (*null)(nil)
|
||||
|
||||
// Start implements streamer
|
||||
func (*null) Start(t *testing.T) Canceler {
|
||||
func (*null) Start(t test.TLegacy) Canceler {
|
||||
return func() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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.
|
||||
*/
|
||||
|
||||
// Defines an interface of commonality between testing.T and logging.TLogger
|
||||
// Allows most library functions to be shared
|
||||
// Simplifies coexistance with TLogger
|
||||
|
||||
package test
|
||||
|
||||
type T interface {
|
||||
Name() string
|
||||
Helper()
|
||||
SkipNow()
|
||||
Log(args ...interface{})
|
||||
Error(args ...interface{})
|
||||
}
|
||||
|
||||
type TLegacy interface {
|
||||
T
|
||||
Logf(fmt string, args ...interface{}) // It gets passed to things in logstream
|
||||
Fatal(args ...interface{})
|
||||
}
|
||||
Loading…
Reference in New Issue