func WaitForEndpointStateWithTimeout(
	kubeClient *KubeClient, logf logging.FormatLogger, theURL string, inState spoof.ResponseChecker,
	desc string, resolvable bool, timeout time.Duration) (*spoof.Response, error) {
	defer logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForEndpointState/%s", desc)).End()
	asURL, err := url.Parse(fmt.Sprintf("http://%s", theURL))
	if err != nil {
		asURL, err = url.Parse(theURL)
		if err != nil {
			return nil, err
		}
	}
	req, err := http.NewRequest(http.MethodGet, asURL.String(), nil)
	if err != nil {
		return nil, err
	}
	client, err := NewSpoofingClient(kubeClient, logf, asURL.Hostname(), resolvable)
	if err != nil {
		return nil, err
	}
	client.RequestTimeout = timeout
	return client.Poll(req, inState)
}
WaitForEndpointStateWithTimeout will poll an endpoint until inState indicates the state is achieved
or the provided timeout is achieved.
If resolvableDomain is false, it will use kubeClientset to look up the ingress and spoof
the domain in the request headers, otherwise it will make the request directly to domain.
desc will be used to name the metric that is emitted to track how long it took for the
domain to get into the state checked by inState.  Commas in `desc` must be escaped.
package test
import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"time"
	"github.com/knative/pkg/test/logging"
	"github.com/knative/pkg/test/spoof"
)
func Retrying(rc spoof.ResponseChecker, codes ...int) spoof.ResponseChecker {
	return func(resp *spoof.Response) (bool, error) {
		for _, code := range codes {
			if resp.StatusCode == code {
				return false, nil
			}
		}
		return rc(resp)
	}
}
func IsOneOfStatusCodes(codes ...int) spoof.ResponseChecker {
	return func(resp *spoof.Response) (bool, error) {
		for _, code := range codes {
			if resp.StatusCode == code {
				return true, nil
			}
		}
		return true, fmt.Errorf("status = %d, want one of: %v", resp.StatusCode, codes)
	}
}
func IsStatusOK(resp *spoof.Response) (bool, error) {
	return IsOneOfStatusCodes(http.StatusOK)(resp)
}
func MatchesBody(expected string) spoof.ResponseChecker {
	return func(resp *spoof.Response) (bool, error) {
		if !strings.Contains(string(resp.Body), expected) {
			return true, fmt.Errorf("body = %s, want: %s", string(resp.Body), expected)
		}
		return true, nil
	}
}
func EventuallyMatchesBody(expected string) spoof.ResponseChecker {
	return func(resp *spoof.Response) (bool, error) {
		if !strings.Contains(string(resp.Body), expected) {
			return false, nil
		}
		return true, nil
	}
}
func MatchesAllOf(checkers ...spoof.ResponseChecker) spoof.ResponseChecker {
	return func(resp *spoof.Response) (bool, error) {
		for _, checker := range checkers {
			done, err := checker(resp)
			if err != nil || !done {
				return done, err
			}
		}
		return true, nil
	}
}
func WaitForEndpointState(kubeClient *KubeClient, logf logging.FormatLogger, theURL string, inState spoof.ResponseChecker, desc string, resolvable bool) (*spoof.Response, error) {
	return WaitForEndpointStateWithTimeout(kubeClient, logf, theURL, inState, desc, resolvable, spoof.RequestTimeout)
}