vitess.io/vitess@v0.16.2/go/event/syslogger/syslogger_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreedto in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package syslogger
    18  
    19  import (
    20  	"fmt"
    21  	"log/syslog"
    22  	"strings"
    23  	"testing"
    24  
    25  	"vitess.io/vitess/go/event"
    26  	"vitess.io/vitess/go/vt/log"
    27  )
    28  
    29  type TestEvent struct {
    30  	triggered bool
    31  	priority  syslog.Priority
    32  	message   string
    33  }
    34  
    35  func (ev *TestEvent) Syslog() (syslog.Priority, string) {
    36  	ev.triggered = true
    37  	return ev.priority, ev.message
    38  }
    39  
    40  var _ Syslogger = (*TestEvent)(nil) // compile-time interface check
    41  
    42  type fakeWriter struct {
    43  	priority syslog.Priority
    44  	message  string
    45  	err      error // if non-nil, force an error to be returned
    46  }
    47  
    48  func (fw *fakeWriter) write(pri syslog.Priority, msg string) error {
    49  	if fw.err != nil {
    50  		return fw.err
    51  	}
    52  
    53  	fw.priority = pri
    54  	fw.message = msg
    55  	return nil
    56  }
    57  func (fw *fakeWriter) Alert(msg string) error   { return fw.write(syslog.LOG_ALERT, msg) }
    58  func (fw *fakeWriter) Crit(msg string) error    { return fw.write(syslog.LOG_CRIT, msg) }
    59  func (fw *fakeWriter) Debug(msg string) error   { return fw.write(syslog.LOG_DEBUG, msg) }
    60  func (fw *fakeWriter) Emerg(msg string) error   { return fw.write(syslog.LOG_EMERG, msg) }
    61  func (fw *fakeWriter) Err(msg string) error     { return fw.write(syslog.LOG_ERR, msg) }
    62  func (fw *fakeWriter) Info(msg string) error    { return fw.write(syslog.LOG_INFO, msg) }
    63  func (fw *fakeWriter) Notice(msg string) error  { return fw.write(syslog.LOG_NOTICE, msg) }
    64  func (fw *fakeWriter) Warning(msg string) error { return fw.write(syslog.LOG_WARNING, msg) }
    65  
    66  type loggerMsg struct {
    67  	msg   string
    68  	level string
    69  }
    70  type testLogger struct {
    71  	logs          []loggerMsg
    72  	savedInfof    func(format string, args ...any)
    73  	savedWarningf func(format string, args ...any)
    74  	savedErrorf   func(format string, args ...any)
    75  }
    76  
    77  func newTestLogger() *testLogger {
    78  	tl := &testLogger{
    79  		savedInfof:    log.Infof,
    80  		savedWarningf: log.Warningf,
    81  		savedErrorf:   log.Errorf,
    82  	}
    83  	log.Infof = tl.recordInfof
    84  	log.Warningf = tl.recordWarningf
    85  	log.Errorf = tl.recordErrorf
    86  	return tl
    87  }
    88  
    89  func (tl *testLogger) Close() {
    90  	log.Infof = tl.savedInfof
    91  	log.Warningf = tl.savedWarningf
    92  	log.Errorf = tl.savedErrorf
    93  }
    94  
    95  func (tl *testLogger) recordInfof(format string, args ...any) {
    96  	msg := fmt.Sprintf(format, args...)
    97  	tl.logs = append(tl.logs, loggerMsg{msg, "INFO"})
    98  	tl.savedInfof(msg)
    99  }
   100  
   101  func (tl *testLogger) recordWarningf(format string, args ...any) {
   102  	msg := fmt.Sprintf(format, args...)
   103  	tl.logs = append(tl.logs, loggerMsg{msg, "WARNING"})
   104  	tl.savedWarningf(msg)
   105  }
   106  
   107  func (tl *testLogger) recordErrorf(format string, args ...any) {
   108  	msg := fmt.Sprintf(format, args...)
   109  	tl.logs = append(tl.logs, loggerMsg{msg, "ERROR"})
   110  	tl.savedErrorf(msg)
   111  }
   112  
   113  func (tl *testLogger) getLog() loggerMsg {
   114  	if len(tl.logs) > 0 {
   115  		return tl.logs[len(tl.logs)-1]
   116  	}
   117  	return loggerMsg{"no logs!", "ERROR"}
   118  }
   119  
   120  // TestSyslog checks that our callback works.
   121  func TestSyslog(t *testing.T) {
   122  	writer = &fakeWriter{}
   123  
   124  	ev := new(TestEvent)
   125  	event.Dispatch(ev)
   126  
   127  	if !ev.triggered {
   128  		t.Errorf("Syslog() was not called on event that implements Syslogger")
   129  	}
   130  }
   131  
   132  // TestBadWriter verifies we are still triggering (to normal logs) if
   133  // the syslog connection failed
   134  func TestBadWriter(t *testing.T) {
   135  	tl := newTestLogger()
   136  	defer tl.Close()
   137  
   138  	writer = nil
   139  	wantMsg := "testing message"
   140  	wantLevel := "ERROR"
   141  	ev := &TestEvent{priority: syslog.LOG_ALERT, message: wantMsg}
   142  	event.Dispatch(ev)
   143  	if !strings.Contains(tl.getLog().msg, wantMsg) {
   144  		t.Errorf("error log msg [%s], want msg [%s]", tl.getLog().msg, wantMsg)
   145  	}
   146  	if !strings.Contains(tl.getLog().level, wantLevel) {
   147  		t.Errorf("error log level [%s], want level [%s]", tl.getLog().level, wantLevel)
   148  	}
   149  	ev = &TestEvent{priority: syslog.LOG_CRIT, message: wantMsg}
   150  	event.Dispatch(ev)
   151  	if !strings.Contains(tl.getLog().level, wantLevel) {
   152  		t.Errorf("error log level [%s], want level [%s]", tl.getLog().level, wantLevel)
   153  	}
   154  	ev = &TestEvent{priority: syslog.LOG_ERR, message: wantMsg}
   155  	event.Dispatch(ev)
   156  	if !strings.Contains(tl.getLog().level, wantLevel) {
   157  		t.Errorf("error log level [%s], want level [%s]", tl.getLog().level, wantLevel)
   158  	}
   159  
   160  	wantLevel = "WARNING"
   161  	ev = &TestEvent{priority: syslog.LOG_WARNING, message: wantMsg}
   162  	event.Dispatch(ev)
   163  	if !strings.Contains(tl.getLog().level, wantLevel) {
   164  		t.Errorf("error log level [%s], want level [%s]", tl.getLog().level, wantLevel)
   165  	}
   166  
   167  	wantLevel = "INFO"
   168  	ev = &TestEvent{priority: syslog.LOG_INFO, message: wantMsg}
   169  	event.Dispatch(ev)
   170  	if !strings.Contains(tl.getLog().level, wantLevel) {
   171  		t.Errorf("error log level [%s], want level [%s]", tl.getLog().level, wantLevel)
   172  	}
   173  	ev = &TestEvent{priority: syslog.LOG_NOTICE, message: wantMsg}
   174  	event.Dispatch(ev)
   175  	if !strings.Contains(tl.getLog().level, wantLevel) {
   176  		t.Errorf("error log level [%s], want level [%s]", tl.getLog().level, wantLevel)
   177  	}
   178  	ev = &TestEvent{priority: syslog.LOG_DEBUG, message: wantMsg}
   179  	event.Dispatch(ev)
   180  	if !strings.Contains(tl.getLog().level, wantLevel) {
   181  		t.Errorf("error log level [%s], want level [%s]", tl.getLog().level, wantLevel)
   182  	}
   183  
   184  	if !ev.triggered {
   185  		t.Errorf("passed nil writer to client")
   186  	}
   187  }
   188  
   189  // TestWriteError checks that we don't panic on a write error.
   190  func TestWriteError(t *testing.T) {
   191  	writer = &fakeWriter{err: fmt.Errorf("forced error")}
   192  
   193  	event.Dispatch(&TestEvent{priority: syslog.LOG_EMERG})
   194  }
   195  
   196  func TestInvalidSeverity(t *testing.T) {
   197  	fw := &fakeWriter{}
   198  	writer = fw
   199  
   200  	event.Dispatch(&TestEvent{priority: syslog.Priority(123), message: "log me"})
   201  
   202  	if fw.message == "log me" {
   203  		t.Errorf("message was logged despite invalid severity")
   204  	}
   205  }
   206  
   207  func testSeverity(sev syslog.Priority, t *testing.T) {
   208  	fw := &fakeWriter{}
   209  	writer = fw
   210  
   211  	event.Dispatch(&TestEvent{priority: sev, message: "log me"})
   212  
   213  	if fw.priority != sev {
   214  		t.Errorf("wrong priority: got %v, want %v", fw.priority, sev)
   215  	}
   216  	if fw.message != "log me" {
   217  		t.Errorf(`wrong message: got "%v", want "%v"`, fw.message, "log me")
   218  	}
   219  }
   220  
   221  func TestEmerg(t *testing.T) {
   222  	testSeverity(syslog.LOG_EMERG, t)
   223  }
   224  
   225  func TestAlert(t *testing.T) {
   226  	testSeverity(syslog.LOG_ALERT, t)
   227  }
   228  
   229  func TestCrit(t *testing.T) {
   230  	testSeverity(syslog.LOG_CRIT, t)
   231  }
   232  
   233  func TestErr(t *testing.T) {
   234  	testSeverity(syslog.LOG_ERR, t)
   235  }
   236  
   237  func TestWarning(t *testing.T) {
   238  	testSeverity(syslog.LOG_WARNING, t)
   239  }
   240  
   241  func TestNotice(t *testing.T) {
   242  	testSeverity(syslog.LOG_NOTICE, t)
   243  }
   244  
   245  func TestInfo(t *testing.T) {
   246  	testSeverity(syslog.LOG_INFO, t)
   247  }
   248  
   249  func TestDebug(t *testing.T) {
   250  	testSeverity(syslog.LOG_DEBUG, t)
   251  }