mirror of https://github.com/tidwall/tile38.git
315 lines
7.7 KiB
Go
315 lines
7.7 KiB
Go
// Copyright 2012-2018 The NATS Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// +build !windows
|
|
|
|
package server
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"syscall"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/gnatsd/logger"
|
|
)
|
|
|
|
func TestSignalToReOpenLogFile(t *testing.T) {
|
|
logFile := "test.log"
|
|
defer os.Remove(logFile)
|
|
defer os.Remove(logFile + ".bak")
|
|
opts := &Options{
|
|
Host: "127.0.0.1",
|
|
Port: -1,
|
|
NoSigs: false,
|
|
LogFile: logFile,
|
|
}
|
|
s := RunServer(opts)
|
|
defer s.SetLogger(nil, false, false)
|
|
defer s.Shutdown()
|
|
|
|
// Set the file log
|
|
fileLog := logger.NewFileLogger(s.opts.LogFile, s.opts.Logtime, s.opts.Debug, s.opts.Trace, true)
|
|
s.SetLogger(fileLog, false, false)
|
|
|
|
// Add a trace
|
|
expectedStr := "This is a Notice"
|
|
s.Noticef(expectedStr)
|
|
buf, err := ioutil.ReadFile(logFile)
|
|
if err != nil {
|
|
t.Fatalf("Error reading file: %v", err)
|
|
}
|
|
if !strings.Contains(string(buf), expectedStr) {
|
|
t.Fatalf("Expected log to contain %q, got %q", expectedStr, string(buf))
|
|
}
|
|
// Rename the file
|
|
if err := os.Rename(logFile, logFile+".bak"); err != nil {
|
|
t.Fatalf("Unable to rename file: %v", err)
|
|
}
|
|
// This should cause file to be reopened.
|
|
syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
|
|
// Wait a bit for action to be performed
|
|
time.Sleep(500 * time.Millisecond)
|
|
buf, err = ioutil.ReadFile(logFile)
|
|
if err != nil {
|
|
t.Fatalf("Error reading file: %v", err)
|
|
}
|
|
expectedStr = "File log re-opened"
|
|
if !strings.Contains(string(buf), expectedStr) {
|
|
t.Fatalf("Expected log to contain %q, got %q", expectedStr, string(buf))
|
|
}
|
|
}
|
|
|
|
func TestSignalToReloadConfig(t *testing.T) {
|
|
opts, err := ProcessConfigFile("./configs/reload/basic.conf")
|
|
if err != nil {
|
|
t.Fatalf("Error processing config file: %v", err)
|
|
}
|
|
opts.NoLog = true
|
|
s := RunServer(opts)
|
|
defer s.Shutdown()
|
|
|
|
// Repeat test to make sure that server services signals more than once...
|
|
for i := 0; i < 2; i++ {
|
|
loaded := s.ConfigTime()
|
|
|
|
// Wait a bit to ensure ConfigTime changes.
|
|
time.Sleep(5 * time.Millisecond)
|
|
|
|
// This should cause config to be reloaded.
|
|
syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
|
|
// Wait a bit for action to be performed
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
if reloaded := s.ConfigTime(); !reloaded.After(loaded) {
|
|
t.Fatalf("ConfigTime is incorrect.\nexpected greater than: %s\ngot: %s", loaded, reloaded)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalNoProcesses(t *testing.T) {
|
|
pgrepBefore := pgrep
|
|
pgrep = func() ([]byte, error) {
|
|
return nil, &exec.ExitError{}
|
|
}
|
|
defer func() {
|
|
pgrep = pgrepBefore
|
|
}()
|
|
|
|
err := ProcessSignal(CommandStop, "")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
expectedStr := "no gnatsd processes running"
|
|
if err.Error() != expectedStr {
|
|
t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalMultipleProcesses(t *testing.T) {
|
|
pid := os.Getpid()
|
|
pgrepBefore := pgrep
|
|
pgrep = func() ([]byte, error) {
|
|
return []byte(fmt.Sprintf("123\n456\n%d\n", pid)), nil
|
|
}
|
|
defer func() {
|
|
pgrep = pgrepBefore
|
|
}()
|
|
|
|
err := ProcessSignal(CommandStop, "")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
expectedStr := "multiple gnatsd processes running:\n123\n456"
|
|
if err.Error() != expectedStr {
|
|
t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalPgrepError(t *testing.T) {
|
|
pgrepBefore := pgrep
|
|
pgrep = func() ([]byte, error) {
|
|
return nil, errors.New("error")
|
|
}
|
|
defer func() {
|
|
pgrep = pgrepBefore
|
|
}()
|
|
|
|
err := ProcessSignal(CommandStop, "")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
expectedStr := "unable to resolve pid, try providing one"
|
|
if err.Error() != expectedStr {
|
|
t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalPgrepMangled(t *testing.T) {
|
|
pgrepBefore := pgrep
|
|
pgrep = func() ([]byte, error) {
|
|
return []byte("12x"), nil
|
|
}
|
|
defer func() {
|
|
pgrep = pgrepBefore
|
|
}()
|
|
|
|
err := ProcessSignal(CommandStop, "")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
expectedStr := "unable to resolve pid, try providing one"
|
|
if err.Error() != expectedStr {
|
|
t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalResolveSingleProcess(t *testing.T) {
|
|
pid := os.Getpid()
|
|
pgrepBefore := pgrep
|
|
pgrep = func() ([]byte, error) {
|
|
return []byte(fmt.Sprintf("123\n%d\n", pid)), nil
|
|
}
|
|
defer func() {
|
|
pgrep = pgrepBefore
|
|
}()
|
|
killBefore := kill
|
|
called := false
|
|
kill = func(pid int, signal syscall.Signal) error {
|
|
called = true
|
|
if pid != 123 {
|
|
t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid)
|
|
}
|
|
if signal != syscall.SIGKILL {
|
|
t.Fatalf("signal is incorrect.\nexpected: killed\ngot: %v", signal)
|
|
}
|
|
return nil
|
|
}
|
|
defer func() {
|
|
kill = killBefore
|
|
}()
|
|
|
|
if err := ProcessSignal(CommandStop, ""); err != nil {
|
|
t.Fatalf("ProcessSignal failed: %v", err)
|
|
}
|
|
|
|
if !called {
|
|
t.Fatal("Expected kill to be called")
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalInvalidCommand(t *testing.T) {
|
|
err := ProcessSignal(Command("invalid"), "123")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
expectedStr := "unknown signal \"invalid\""
|
|
if err.Error() != expectedStr {
|
|
t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalInvalidPid(t *testing.T) {
|
|
err := ProcessSignal(CommandStop, "abc")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
expectedStr := "invalid pid: abc"
|
|
if err.Error() != expectedStr {
|
|
t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalQuitProcess(t *testing.T) {
|
|
killBefore := kill
|
|
called := false
|
|
kill = func(pid int, signal syscall.Signal) error {
|
|
called = true
|
|
if pid != 123 {
|
|
t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid)
|
|
}
|
|
if signal != syscall.SIGINT {
|
|
t.Fatalf("signal is incorrect.\nexpected: interrupt\ngot: %v", signal)
|
|
}
|
|
return nil
|
|
}
|
|
defer func() {
|
|
kill = killBefore
|
|
}()
|
|
|
|
if err := ProcessSignal(CommandQuit, "123"); err != nil {
|
|
t.Fatalf("ProcessSignal failed: %v", err)
|
|
}
|
|
|
|
if !called {
|
|
t.Fatal("Expected kill to be called")
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalReopenProcess(t *testing.T) {
|
|
killBefore := kill
|
|
called := false
|
|
kill = func(pid int, signal syscall.Signal) error {
|
|
called = true
|
|
if pid != 123 {
|
|
t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid)
|
|
}
|
|
if signal != syscall.SIGUSR1 {
|
|
t.Fatalf("signal is incorrect.\nexpected: user defined signal 1\ngot: %v", signal)
|
|
}
|
|
return nil
|
|
}
|
|
defer func() {
|
|
kill = killBefore
|
|
}()
|
|
|
|
if err := ProcessSignal(CommandReopen, "123"); err != nil {
|
|
t.Fatalf("ProcessSignal failed: %v", err)
|
|
}
|
|
|
|
if !called {
|
|
t.Fatal("Expected kill to be called")
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalReloadProcess(t *testing.T) {
|
|
killBefore := kill
|
|
called := false
|
|
kill = func(pid int, signal syscall.Signal) error {
|
|
called = true
|
|
if pid != 123 {
|
|
t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid)
|
|
}
|
|
if signal != syscall.SIGHUP {
|
|
t.Fatalf("signal is incorrect.\nexpected: hangup\ngot: %v", signal)
|
|
}
|
|
return nil
|
|
}
|
|
defer func() {
|
|
kill = killBefore
|
|
}()
|
|
|
|
if err := ProcessSignal(CommandReload, "123"); err != nil {
|
|
t.Fatalf("ProcessSignal failed: %v", err)
|
|
}
|
|
|
|
if !called {
|
|
t.Fatal("Expected kill to be called")
|
|
}
|
|
}
|