github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/gopkg.in/mgo.v2/suite_test.go (about)

     1  // mgo - MongoDB driver for Go
     2  //
     3  // Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net>
     4  //
     5  // All rights reserved.
     6  //
     7  // Redistribution and use in source and binary forms, with or without
     8  // modification, are permitted provided that the following conditions are met:
     9  //
    10  // 1. Redistributions of source code must retain the above copyright notice, this
    11  //    list of conditions and the following disclaimer.
    12  // 2. Redistributions in binary form must reproduce the above copyright notice,
    13  //    this list of conditions and the following disclaimer in the documentation
    14  //    and/or other materials provided with the distribution.
    15  //
    16  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    17  // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    18  // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    19  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    20  // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    21  // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    22  // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    23  // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    24  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    25  // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    26  
    27  package mgo_test
    28  
    29  import (
    30  	"bytes"
    31  	"errors"
    32  	"flag"
    33  	"fmt"
    34  	"net"
    35  	"os/exec"
    36  	"runtime"
    37  	"strconv"
    38  	"testing"
    39  	"time"
    40  
    41  	. "gopkg.in/check.v1"
    42  	"gopkg.in/mgo.v2"
    43  	"gopkg.in/mgo.v2/bson"
    44  )
    45  
    46  var fast = flag.Bool("fast", false, "Skip slow tests")
    47  
    48  type M bson.M
    49  
    50  type cLogger C
    51  
    52  func (c *cLogger) Output(calldepth int, s string) error {
    53  	ns := time.Now().UnixNano()
    54  	t := float64(ns%100e9) / 1e9
    55  	((*C)(c)).Logf("[LOG] %.05f %s", t, s)
    56  	return nil
    57  }
    58  
    59  func TestAll(t *testing.T) {
    60  	TestingT(t)
    61  }
    62  
    63  type S struct {
    64  	session *mgo.Session
    65  	stopped bool
    66  	build   mgo.BuildInfo
    67  	frozen  []string
    68  }
    69  
    70  func (s *S) versionAtLeast(v ...int) (result bool) {
    71  	for i := range v {
    72  		if i == len(s.build.VersionArray) {
    73  			return false
    74  		}
    75  		if s.build.VersionArray[i] != v[i] {
    76  			return s.build.VersionArray[i] >= v[i]
    77  		}
    78  	}
    79  	return true
    80  }
    81  
    82  var _ = Suite(&S{})
    83  
    84  func (s *S) SetUpSuite(c *C) {
    85  	mgo.SetDebug(true)
    86  	mgo.SetStats(true)
    87  	s.StartAll()
    88  
    89  	session, err := mgo.Dial("localhost:40001")
    90  	c.Assert(err, IsNil)
    91  	s.build, err = session.BuildInfo()
    92  	c.Check(err, IsNil)
    93  	session.Close()
    94  }
    95  
    96  func (s *S) SetUpTest(c *C) {
    97  	err := run("mongo --nodb harness/mongojs/dropall.js")
    98  	if err != nil {
    99  		panic(err.Error())
   100  	}
   101  	mgo.SetLogger((*cLogger)(c))
   102  	mgo.ResetStats()
   103  }
   104  
   105  func (s *S) TearDownTest(c *C) {
   106  	if s.stopped {
   107  		s.Stop(":40201")
   108  		s.Stop(":40202")
   109  		s.Stop(":40203")
   110  		s.StartAll()
   111  	}
   112  	for _, host := range s.frozen {
   113  		if host != "" {
   114  			s.Thaw(host)
   115  		}
   116  	}
   117  	var stats mgo.Stats
   118  	for i := 0; ; i++ {
   119  		stats = mgo.GetStats()
   120  		if stats.SocketsInUse == 0 && stats.SocketsAlive == 0 {
   121  			break
   122  		}
   123  		if i == 20 {
   124  			c.Fatal("Test left sockets in a dirty state")
   125  		}
   126  		c.Logf("Waiting for sockets to die: %d in use, %d alive", stats.SocketsInUse, stats.SocketsAlive)
   127  		time.Sleep(500 * time.Millisecond)
   128  	}
   129  	for i := 0; ; i++ {
   130  		stats = mgo.GetStats()
   131  		if stats.Clusters == 0 {
   132  			break
   133  		}
   134  		if i == 60 {
   135  			c.Fatal("Test left clusters alive")
   136  		}
   137  		c.Logf("Waiting for clusters to die: %d alive", stats.Clusters)
   138  		time.Sleep(1 * time.Second)
   139  	}
   140  }
   141  
   142  func (s *S) Stop(host string) {
   143  	// Give a moment for slaves to sync and avoid getting rollback issues.
   144  	panicOnWindows()
   145  	time.Sleep(2 * time.Second)
   146  	err := run("svc -d _harness/daemons/" + supvName(host))
   147  	if err != nil {
   148  		panic(err)
   149  	}
   150  	s.stopped = true
   151  }
   152  
   153  func (s *S) pid(host string) int {
   154  	// Note recent releases of lsof force 'f' to be present in the output (WTF?).
   155  	cmd := exec.Command("lsof", "-iTCP:"+hostPort(host), "-sTCP:LISTEN", "-Fpf")
   156  	output, err := cmd.CombinedOutput()
   157  	if err != nil {
   158  		panic(err)
   159  	}
   160  	pidstr := string(bytes.Fields(output[1:])[0])
   161  	pid, err := strconv.Atoi(pidstr)
   162  	if err != nil {
   163  		panic(fmt.Errorf("cannot convert pid to int: %q, command line: %q", pidstr, cmd.Args))
   164  	}
   165  	return pid
   166  }
   167  
   168  func (s *S) Freeze(host string) {
   169  	err := stop(s.pid(host))
   170  	if err != nil {
   171  		panic(err)
   172  	}
   173  	s.frozen = append(s.frozen, host)
   174  }
   175  
   176  func (s *S) Thaw(host string) {
   177  	err := cont(s.pid(host))
   178  	if err != nil {
   179  		panic(err)
   180  	}
   181  	for i, frozen := range s.frozen {
   182  		if frozen == host {
   183  			s.frozen[i] = ""
   184  		}
   185  	}
   186  }
   187  
   188  func (s *S) StartAll() {
   189  	if s.stopped {
   190  		// Restart any stopped nodes.
   191  		run("svc -u _harness/daemons/*")
   192  		err := run("mongo --nodb harness/mongojs/wait.js")
   193  		if err != nil {
   194  			panic(err)
   195  		}
   196  		s.stopped = false
   197  	}
   198  }
   199  
   200  func run(command string) error {
   201  	var output []byte
   202  	var err error
   203  	if runtime.GOOS == "windows" {
   204  		output, err = exec.Command("cmd", "/C", command).CombinedOutput()
   205  	} else {
   206  		output, err = exec.Command("/bin/sh", "-c", command).CombinedOutput()
   207  	}
   208  
   209  	if err != nil {
   210  		msg := fmt.Sprintf("Failed to execute: %s: %s\n%s", command, err.Error(), string(output))
   211  		return errors.New(msg)
   212  	}
   213  	return nil
   214  }
   215  
   216  var supvNames = map[string]string{
   217  	"40001": "db1",
   218  	"40002": "db2",
   219  	"40011": "rs1a",
   220  	"40012": "rs1b",
   221  	"40013": "rs1c",
   222  	"40021": "rs2a",
   223  	"40022": "rs2b",
   224  	"40023": "rs2c",
   225  	"40031": "rs3a",
   226  	"40032": "rs3b",
   227  	"40033": "rs3c",
   228  	"40041": "rs4a",
   229  	"40101": "cfg1",
   230  	"40102": "cfg2",
   231  	"40103": "cfg3",
   232  	"40201": "s1",
   233  	"40202": "s2",
   234  	"40203": "s3",
   235  }
   236  
   237  // supvName returns the daemon name for the given host address.
   238  func supvName(host string) string {
   239  	host, port, err := net.SplitHostPort(host)
   240  	if err != nil {
   241  		panic(err)
   242  	}
   243  	name, ok := supvNames[port]
   244  	if !ok {
   245  		panic("Unknown host: " + host)
   246  	}
   247  	return name
   248  }
   249  
   250  func hostPort(host string) string {
   251  	_, port, err := net.SplitHostPort(host)
   252  	if err != nil {
   253  		panic(err)
   254  	}
   255  	return port
   256  }
   257  
   258  func panicOnWindows() {
   259  	if runtime.GOOS == "windows" {
   260  		panic("the test suite is not yet fully supported on Windows")
   261  	}
   262  }