@@ -80,6 +80,9 @@ const (
8080// By default, we allocate 20% of available memory to the test server.
8181const defaultStoreMemSize = 0.2
8282
83+ const defaultInitTimeout = 60
84+ const defaultPollListenURLTimeout = 60
85+
8386const testserverMessagePrefix = "cockroach-go testserver"
8487const tenantserverMessagePrefix = "cockroach-go tenantserver"
8588
@@ -212,19 +215,21 @@ type TestConfig struct {
212215}
213216
214217type testServerArgs struct {
215- secure bool
216- rootPW string // if nonempty, set as pw for root
217- storeOnDisk bool // to save database in disk
218- storeMemSize float64 // the proportion of available memory allocated to test server
219- httpPorts []int
220- listenAddrPorts []int
221- testConfig TestConfig
222- nonStableDB bool
223- customVersion string // custom cockroach version to use
224- cockroachBinary string // path to cockroach executable file
225- upgradeCockroachBinary string // path to cockroach binary for upgrade
226- numNodes int
227- externalIODir string
218+ secure bool
219+ rootPW string // if nonempty, set as pw for root
220+ storeOnDisk bool // to save database in disk
221+ storeMemSize float64 // the proportion of available memory allocated to test server
222+ httpPorts []int
223+ listenAddrPorts []int
224+ testConfig TestConfig
225+ nonStableDB bool
226+ customVersion string // custom cockroach version to use
227+ cockroachBinary string // path to cockroach executable file
228+ upgradeCockroachBinary string // path to cockroach binary for upgrade
229+ numNodes int
230+ externalIODir string
231+ initTimeoutSeconds int
232+ pollListenURLTimeoutSeconds int
228233}
229234
230235// CockroachBinaryPathOpt is a TestServer option that can be passed to
@@ -349,6 +354,18 @@ func ExternalIODirOpt(ioDir string) TestServerOpt {
349354 }
350355}
351356
357+ func InitTimeoutOpt (timeout int ) TestServerOpt {
358+ return func (args * testServerArgs ) {
359+ args .initTimeoutSeconds = timeout
360+ }
361+ }
362+
363+ func PollListenURLTimeoutOpt (timeout int ) TestServerOpt {
364+ return func (args * testServerArgs ) {
365+ args .pollListenURLTimeoutSeconds = timeout
366+ }
367+ }
368+
352369const (
353370 logsDirName = "logs"
354371 certsDirName = "certs"
@@ -365,6 +382,8 @@ var errStoppedInMiddle = errors.New("download stopped in middle")
365382func NewTestServer (opts ... TestServerOpt ) (TestServer , error ) {
366383 serverArgs := & testServerArgs {numNodes : 1 }
367384 serverArgs .storeMemSize = defaultStoreMemSize
385+ serverArgs .initTimeoutSeconds = defaultInitTimeout
386+ serverArgs .pollListenURLTimeoutSeconds = defaultPollListenURLTimeout
368387 for _ , applyOptToArgs := range opts {
369388 applyOptToArgs (serverArgs )
370389 }
@@ -632,7 +651,7 @@ func (ts *testServerImpl) WaitForInitFinishForNode(nodeNum int) error {
632651 defer func () {
633652 _ = db .Close ()
634653 }()
635- for i := 0 ; i < 100 ; i ++ {
654+ for i := 0 ; i < ts . serverArgs . initTimeoutSeconds * 10 ; i ++ {
636655 if err = db .Ping (); err == nil {
637656 return nil
638657 }
@@ -649,22 +668,27 @@ func (ts *testServerImpl) WaitForInit() error {
649668
650669func (ts * testServerImpl ) pollListeningURLFile (nodeNum int ) error {
651670 var data []byte
652- for {
671+ for i := 0 ; i < ts . serverArgs . pollListenURLTimeoutSeconds * 10 ; i ++ {
653672 ts .mu .RLock ()
654673 state := ts .nodes [nodeNum ].state
655674 ts .mu .RUnlock ()
656675 if state != stateRunning {
657676 return fmt .Errorf ("server stopped or crashed before listening URL file was available" )
658677 }
659-
660678 var err error
661679 data , err = ioutil .ReadFile (ts .nodes [nodeNum ].listeningURLFile )
662- if err == nil {
680+ if len (data ) == 0 {
681+ time .Sleep (100 * time .Millisecond )
682+ continue
683+ } else if err == nil {
663684 break
664685 } else if ! os .IsNotExist (err ) {
665686 return fmt .Errorf ("unexpected error while reading listening URL file: %w" , err )
666687 }
667- time .Sleep (100 * time .Millisecond )
688+ }
689+
690+ if len (data ) == 0 {
691+ panic ("empty connection string" )
668692 }
669693
670694 u , err := url .Parse (string (bytes .TrimSpace (data )))
@@ -765,15 +789,33 @@ func (ts *testServerImpl) Stop() {
765789 }
766790
767791 ts .serverState = stateStopped
768- for _ , node := range ts .nodes {
792+ for i , node := range ts .nodes {
769793 cmd := node .startCmd
770794 if cmd .Process != nil {
771795 _ = cmd .Process .Kill ()
772796 }
773797
798+ if node .state != stateFailed {
799+ node .state = stateStopped
800+ }
801+
774802 if node .state != stateStopped {
775803 ts .serverState = stateFailed
776804 }
805+
806+ // RUnlock such that StopNode can Lock and Unlock.
807+ ts .mu .RUnlock ()
808+ err := ts .StopNode (i )
809+ if err != nil {
810+ log .Printf ("error stopping node %d: %s" , i , err )
811+ }
812+ ts .mu .RLock ()
813+
814+ nodeDir := fmt .Sprintf ("%s%d" , ts .baseDir , i )
815+ if err := os .RemoveAll (nodeDir ); err != nil {
816+ log .Printf ("error deleting tmp directory %s for node: %s" , nodeDir , err )
817+ }
818+
777819 }
778820
779821 // Only cleanup on intentional stops.
0 commit comments