...

Source file src/github.com/gomodule/redigo/redis/test_test.go

Documentation: github.com/gomodule/redigo/redis

     1  // Copyright 2012 Gary Burd
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // 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, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package redis
    16  
    17  import (
    18  	"bufio"
    19  	"errors"
    20  	"flag"
    21  	"fmt"
    22  	"io"
    23  	"io/ioutil"
    24  	"os"
    25  	"os/exec"
    26  	"strconv"
    27  	"strings"
    28  	"sync"
    29  	"testing"
    30  	"time"
    31  )
    32  
    33  func SetNowFunc(f func() time.Time) {
    34  	nowFunc = f
    35  }
    36  
    37  var (
    38  	ErrNegativeInt = errNegativeInt
    39  
    40  	serverPath     = flag.String("redis-server", "redis-server", "Path to redis server binary")
    41  	serverAddress  = flag.String("redis-address", "127.0.0.1", "The address of the server")
    42  	serverBasePort = flag.Int("redis-port", 16379, "Beginning of port range for test servers")
    43  	serverLogName  = flag.String("redis-log", "", "Write Redis server logs to `filename`")
    44  	serverLog      = ioutil.Discard
    45  
    46  	defaultServerMu  sync.Mutex
    47  	defaultServer    *Server
    48  	defaultServerErr error
    49  )
    50  
    51  type Server struct {
    52  	name string
    53  	cmd  *exec.Cmd
    54  	done chan struct{}
    55  }
    56  
    57  func NewServer(name string, args ...string) (*Server, error) {
    58  	s := &Server{
    59  		name: name,
    60  		cmd:  exec.Command(*serverPath, args...),
    61  		done: make(chan struct{}),
    62  	}
    63  
    64  	r, err := s.cmd.StdoutPipe()
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	err = s.cmd.Start()
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	ready := make(chan error, 1)
    75  	go s.watch(r, ready)
    76  
    77  	select {
    78  	case err = <-ready:
    79  	case <-time.After(time.Second * 10):
    80  		err = errors.New("timeout waiting for server to start")
    81  	}
    82  
    83  	if err != nil {
    84  		s.Stop()
    85  		return nil, err
    86  	}
    87  
    88  	return s, nil
    89  }
    90  
    91  func (s *Server) watch(r io.Reader, ready chan error) {
    92  	fmt.Fprintf(serverLog, "%d START %s \n", s.cmd.Process.Pid, s.name)
    93  	var listening bool
    94  	var text string
    95  	scn := bufio.NewScanner(r)
    96  	for scn.Scan() {
    97  		text = scn.Text()
    98  		fmt.Fprintf(serverLog, "%s\n", text)
    99  		if !listening {
   100  			if strings.Contains(text, " * Ready to accept connections") ||
   101  				strings.Contains(text, " * The server is now ready to accept connections on port") {
   102  				listening = true
   103  				ready <- nil
   104  			}
   105  		}
   106  	}
   107  	if !listening {
   108  		ready <- fmt.Errorf("server exited: %s", text)
   109  	}
   110  	s.cmd.Wait()
   111  	fmt.Fprintf(serverLog, "%d STOP %s \n", s.cmd.Process.Pid, s.name)
   112  	close(s.done)
   113  }
   114  
   115  func (s *Server) Stop() {
   116  	s.cmd.Process.Signal(os.Interrupt)
   117  	<-s.done
   118  }
   119  
   120  // stopDefaultServer stops the server created by DialDefaultServer.
   121  func stopDefaultServer() {
   122  	defaultServerMu.Lock()
   123  	defer defaultServerMu.Unlock()
   124  	if defaultServer != nil {
   125  		defaultServer.Stop()
   126  		defaultServer = nil
   127  	}
   128  }
   129  
   130  // DefaultServerAddr starts the test server if not already started and returns
   131  // the address of that server.
   132  func DefaultServerAddr() (string, error) {
   133  	defaultServerMu.Lock()
   134  	defer defaultServerMu.Unlock()
   135  	addr := fmt.Sprintf("%v:%d", *serverAddress, *serverBasePort)
   136  	if defaultServer != nil || defaultServerErr != nil {
   137  		return addr, defaultServerErr
   138  	}
   139  	defaultServer, defaultServerErr = NewServer(
   140  		"default",
   141  		"--port", strconv.Itoa(*serverBasePort),
   142  		"--bind", *serverAddress,
   143  		"--save", "",
   144  		"--appendonly", "no")
   145  	return addr, defaultServerErr
   146  }
   147  
   148  // DialDefaultServer starts the test server if not already started and dials a
   149  // connection to the server.
   150  func DialDefaultServer() (Conn, error) {
   151  	addr, err := DefaultServerAddr()
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	c, err := Dial("tcp", addr, DialReadTimeout(1*time.Second), DialWriteTimeout(1*time.Second))
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	c.Do("FLUSHDB")
   160  	return c, nil
   161  }
   162  
   163  func TestMain(m *testing.M) {
   164  	os.Exit(func() int {
   165  		flag.Parse()
   166  
   167  		var f *os.File
   168  		if *serverLogName != "" {
   169  			var err error
   170  			f, err = os.OpenFile(*serverLogName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
   171  			if err != nil {
   172  				fmt.Fprintf(os.Stderr, "Error opening redis-log: %v\n", err)
   173  				return 1
   174  			}
   175  			defer f.Close()
   176  			serverLog = f
   177  		}
   178  
   179  		defer stopDefaultServer()
   180  
   181  		return m.Run()
   182  	}())
   183  }
   184  

View as plain text