go.etcd.io/etcd@v3.3.27+incompatible/pkg/testutil/testutil.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package testutil provides test utility functions. 16 package testutil 17 18 import ( 19 "net/url" 20 "runtime" 21 "testing" 22 "time" 23 ) 24 25 // WaitSchedule briefly sleeps in order to invoke the go scheduler. 26 // TODO: improve this when we are able to know the schedule or status of target go-routine. 27 func WaitSchedule() { 28 time.Sleep(10 * time.Millisecond) 29 } 30 31 func MustNewURLs(t *testing.T, urls []string) []url.URL { 32 if urls == nil { 33 return nil 34 } 35 var us []url.URL 36 for _, url := range urls { 37 u := MustNewURL(t, url) 38 us = append(us, *u) 39 } 40 return us 41 } 42 43 func MustNewURL(t *testing.T, s string) *url.URL { 44 u, err := url.Parse(s) 45 if err != nil { 46 t.Fatalf("parse %v error: %v", s, err) 47 } 48 return u 49 } 50 51 // FatalStack helps to fatal the test and print out the stacks of all running goroutines. 52 func FatalStack(t *testing.T, s string) { 53 stackTrace := make([]byte, 1024*1024) 54 n := runtime.Stack(stackTrace, true) 55 t.Error(string(stackTrace[:n])) 56 t.Fatalf(s) 57 } 58 59 // ConditionFunc returns true when a condition is met. 60 type ConditionFunc func() (bool, error) 61 62 // Poll calls a condition function repeatedly on a polling interval until it returns true, returns an error 63 // or the timeout is reached. If the condition function returns true or an error before the timeout, Poll 64 // immediately returns with the true value or the error. If the timeout is exceeded, Poll returns false. 65 func Poll(interval time.Duration, timeout time.Duration, condition ConditionFunc) (bool, error) { 66 timeoutCh := time.After(timeout) 67 ticker := time.NewTicker(interval) 68 defer ticker.Stop() 69 70 for { 71 select { 72 case <-timeoutCh: 73 return false, nil 74 case <-ticker.C: 75 success, err := condition() 76 if err != nil { 77 return false, err 78 } 79 if success { 80 return true, nil 81 } 82 } 83 } 84 }