diff --git a/utils/coreutils.go b/utils/coreutils.go index c05d73dda..ce14ff570 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -966,11 +966,8 @@ func AESDecrypt(encrypted string, encKey string) (txt string, err error) { nonceSize := aesGCM.NonceSize() nonce, ciphertext := enc[:nonceSize], enc[nonceSize:] var plaintext []byte - if plaintext, err = aesGCM.Open(nil, nonce, ciphertext, nil); err != nil { - return - } - - return fmt.Sprintf("%s", plaintext), nil + plaintext, err = aesGCM.Open(nil, nonce, ciphertext, nil) + return string(plaintext), err } // Hash generates the hash text diff --git a/utils/file.go b/utils/file.go index 0c56f1835..573beb3be 100644 --- a/utils/file.go +++ b/utils/file.go @@ -26,8 +26,7 @@ import ( // WatchDir sets up a watcher via inotify to be triggered on new files // sysID is the subsystem ID, f will be triggered on match -func WatchDir(dirPath string, f func(itmPath, itmID string) error, - sysID string, stopWatching chan struct{}) (err error) { +func WatchDir(dirPath string, f func(itmPath, itmID string) error, sysID string, stopWatching chan struct{}) (err error) { var watcher *fsnotify.Watcher if watcher, err = fsnotify.NewWatcher(); err != nil { return diff --git a/utils/file_it_test.go b/utils/file_it_test.go new file mode 100644 index 000000000..925cabff2 --- /dev/null +++ b/utils/file_it_test.go @@ -0,0 +1,62 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package utils + +import ( + "os" + "testing" +) + +var ( + testsWatchDir = []func(t *testing.T){ + testWatchDir, + testWatchDirNoError, + } +) + +func TestFileIT(t *testing.T) { + for _, test := range testsWatchDir { + t.Run("Watch_Dir_Tests", test) + } +} + +func testWatchDir(t *testing.T) { + stopWatching := make(chan struct{}, 1) + close(stopWatching) + flPath := "/tmp/testWatchDir" + if err := os.MkdirAll(flPath, 0777); err != nil { + t.Error(err) + } + if err := WatchDir(flPath, nil, "randomID", stopWatching); err != nil { + t.Error(err) + } + + if err := os.RemoveAll(flPath); err != nil { + t.Fatal(err) + } +} + +func testWatchDirNoError(t *testing.T) { + stopWatching := make(chan struct{}, 1) + flPath := "/tmp/inexistentDir" + expectedErr := "no such file or directory" + if err := WatchDir(flPath, nil, "randomID", stopWatching); err == nil || err.Error() != expectedErr { + t.Errorf("Expected %+v, received %+v", expectedErr, err) + } +} diff --git a/utils/logger.go b/utils/logger.go index f769ebc2b..0d340eedc 100644 --- a/utils/logger.go +++ b/utils/logger.go @@ -31,10 +31,7 @@ var nodeID string func init() { if Logger == nil || reflect.ValueOf(Logger).IsNil() { - err := Newlogger(MetaSysLog, nodeID) - if err != nil { - Logger.Err(fmt.Sprintf("Could not connect to syslog: %v", err)) - } + Newlogger(MetaSysLog, nodeID) } } @@ -44,12 +41,9 @@ func Newlogger(loggertype, id string) (err error) { nodeID = id var l *syslog.Writer if loggertype == MetaSysLog { - if l, err = syslog.New(syslog.LOG_INFO|syslog.LOG_DAEMON, fmt.Sprintf("CGRateS <%s> ", nodeID)); err != nil { - return err - } else { - Logger.SetSyslog(l) - } - return nil + l, err = syslog.New(syslog.LOG_INFO|syslog.LOG_DAEMON, fmt.Sprintf("CGRateS <%s> ", nodeID)) + Logger.SetSyslog(l) // if we received an error, l is nil + return err } else if loggertype != MetaStdLog { return fmt.Errorf("unsuported logger: <%s>", loggertype) } @@ -92,7 +86,7 @@ type StdLogger struct { func (sl *StdLogger) Close() (err error) { if sl.syslog != nil { - sl.Close() + err = sl.syslog.Close() } return } diff --git a/utils/logger_it_test.go b/utils/logger_it_test.go new file mode 100644 index 000000000..6b44fe45a --- /dev/null +++ b/utils/logger_it_test.go @@ -0,0 +1,350 @@ +package utils + +import ( + "bytes" + "log/syslog" + "net" + "runtime" + "strings" + "testing" +) + +var ( + testsSyslogLogger = []func(t *testing.T){ + testEmergencyLogger, + testAlertLogger, + testCriticalLogger, + testErrorLogger, + testWarningLogger, + testNoticeLogger, + testInfoLogger, + testDebugLogger, + } +) + +type unixServer struct { + l net.Listener + buf *bytes.Buffer + path string +} + +func newUnixServer(path string) (*unixServer, error) { + l, err := net.Listen("unix", path) + if err != nil { + return nil, err + } + return &unixServer{ + l: l, + buf: new(bytes.Buffer), + path: path, + }, nil +} + +func (u *unixServer) Close() error { + return u.l.Close() +} + +func (u *unixServer) serveConn(c net.Conn) error { + for { + buf := make([]byte, 512) + nr, err := c.Read(buf) + if err != nil { + return err + } + + _, err = u.buf.Write(buf[0:nr]) + if err != nil { + return err + } + } +} + +func (u *unixServer) Serve() error { + for { + fd, err := u.l.Accept() + if err != nil { + return err + } + + go u.serveConn(fd) + } +} + +func (u *unixServer) String() string { + return u.buf.String() +} + +func TestLoggerSyslog(t *testing.T) { + for _, test := range testsSyslogLogger { + t.Run("Syslog_logger", test) + } +} + +func testEmergencyLogger(t *testing.T) { + flPath := "/tmp/testEmergency2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_EMERG, "id_emergency") + if err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + + if err := newLogger.Emerg("emergency_panic"); err != nil { + t.Error(err) + } + runtime.Gosched() + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "emergency_panic" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} + +func testAlertLogger(t *testing.T) { + flPath := "/tmp/testAlert2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_ALERT, "id_alert") + if err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + + newLogger.SetLogLevel(7) + + if err := newLogger.Alert("emergency_alert"); err != nil { + t.Error(err) + } + runtime.Gosched() + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "emergency_alert" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} + +func testCriticalLogger(t *testing.T) { + flPath := "/tmp/testCritical2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_CRIT, "id_critical") + if err != nil { + t.Error(err) + } + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + newLogger.SetLogLevel(7) + + if err := newLogger.Crit("critical_panic"); err != nil { + t.Error(err) + } + runtime.Gosched() + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "critical_panic" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} + +func testErrorLogger(t *testing.T) { + flPath := "/tmp/testError2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_ERR, "id_error") + if err != nil { + t.Error(err) + } + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + newLogger.SetLogLevel(7) + + if err := newLogger.Err("error_panic"); err != nil { + t.Error(err) + } + runtime.Gosched() + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "error_panic" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} + +func testWarningLogger(t *testing.T) { + flPath := "/tmp/testWarning2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_WARNING, "id_warning") + if err != nil { + t.Error(err) + } + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + newLogger.SetLogLevel(7) + + if err := newLogger.Warning("warning_panic"); err != nil { + t.Error(err) + } + runtime.Gosched() + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} + +func testNoticeLogger(t *testing.T) { + flPath := "/tmp/testNotice2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_NOTICE, "id_notice") + if err != nil { + t.Error(err) + } + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + newLogger.SetLogLevel(7) + + if err := newLogger.Notice("notice_panic"); err != nil { + t.Error(err) + } + runtime.Gosched() + + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "notice_panic" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} + +func testInfoLogger(t *testing.T) { + flPath := "/tmp/testInfo2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_NOTICE, "id_info") + if err != nil { + t.Error(err) + } + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + newLogger.SetLogLevel(7) + + if err := newLogger.Info("info_panic"); err != nil { + t.Error(err) + } + runtime.Gosched() + + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "info_panic" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} + +func testDebugLogger(t *testing.T) { + flPath := "/tmp/testDebug2" + + l, err := newUnixServer(flPath) + if err != nil { + t.Error(err) + } + go l.Serve() + + writer, err := syslog.Dial("unix", flPath, syslog.LOG_NOTICE, "id_debug") + if err != nil { + t.Error(err) + } + newLogger := new(StdLogger) + newLogger.SetSyslog(writer) + newLogger.SetLogLevel(7) + + if err := newLogger.Debug("debug_panic"); err != nil { + t.Error(err) + } + runtime.Gosched() + + if err := writer.Close(); err != nil { + t.Error(err) + } + if err := l.Close(); err != nil { + t.Error(err) + } + expected := "debug_panic" + if rcv := l.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %q, received %q", expected, rcv) + } +} diff --git a/utils/logger_test.go b/utils/logger_test.go new file mode 100644 index 000000000..7f9720f01 --- /dev/null +++ b/utils/logger_test.go @@ -0,0 +1,324 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package utils + +import ( + "bytes" + "io/ioutil" + "log" + syslog "log/syslog" + "os" + "strings" + "testing" +) + +func TestEmergLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + loggertype := MetaSysLog + id := "id_emerg" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(-1) + if err := newLogger.Emerg(EmptyString); err != nil { + t.Error(err) + } else { + newLogger.SetLogLevel(LOGLEVEL_EMERGENCY) + if err := newLogger.Emerg("emergency_panic"); err != nil { + t.Error(err) + } + expected := "CGRateS [EMERGENCY] emergency_panic" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestAlertLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + loggertype := MetaSysLog + id := "id_alert" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(0) + if err := newLogger.Alert("Alert"); err != nil { + t.Error(err) + } else { + newLogger.SetLogLevel(LOGLEVEL_ALERT) + if err := newLogger.Alert("Alert"); err != nil { + t.Error(err) + } + expected := "CGRateS [ALERT] Alert" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestCritLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + + loggertype := MetaSysLog + id := "id_crit" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(1) + if err := newLogger.Crit("Critical_level"); err != nil { + t.Error(err) + } else { + newLogger.logLevel = LOGLEVEL_CRITICAL + if err := newLogger.Crit("Critical_level"); err != nil { + t.Error(err) + } + expected := "CGRateS [CRITICAL] Critical_level" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestErrorLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + + loggertype := MetaSysLog + id := "id_error" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(2) + if err := newLogger.Err("error_panic"); err != nil { + t.Error(err) + } else { + newLogger.SetLogLevel(LOGLEVEL_ERROR) + if err := newLogger.Err("error_panic"); err != nil { + t.Error(err) + } + expected := "CGRateS [ERROR] error_panic" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestWarningLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + + loggertype := MetaSysLog + id := "id_error" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(3) + if err := newLogger.Warning("warning_panic"); err != nil { + t.Error(err) + } else { + newLogger.SetLogLevel(LOGLEVEL_WARNING) + if err := newLogger.Warning("warning_panic"); err != nil { + t.Error(err) + } + expected := "CGRateS [WARNING] warning_panic" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestNoticeLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + + loggertype := MetaSysLog + id := "id_notice" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(4) + if err := newLogger.Notice("notice_panic"); err != nil { + t.Error(err) + } else { + newLogger.SetLogLevel(LOGLEVEL_NOTICE) + if err := newLogger.Notice("notice_panic"); err != nil { + t.Error(err) + } + expected := "CGRateS [NOTICE] notice_panic" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestInfoLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + + loggertype := MetaSysLog + id := "id_info" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(5) + if err := newLogger.Info("info_panic"); err != nil { + t.Error(err) + } else { + newLogger.SetLogLevel(LOGLEVEL_INFO) + if err := newLogger.Info("info_panic"); err != nil { + t.Error(err) + } + expected := "CGRateS [INFO] info_panic" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestDebugLogger(t *testing.T) { + output := new(bytes.Buffer) + log.SetOutput(output) + + loggertype := MetaSysLog + id := "id_debug" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + + newLogger.SetLogLevel(6) + if err := newLogger.Debug("debug_panic"); err != nil { + t.Error(err) + } else { + newLogger.SetLogLevel(LOGLEVEL_DEBUG) + if err := newLogger.Debug("debug_panic"); err != nil { + t.Error(err) + } + newLogger.GetSyslog() + expected := "GRateS [DEBUG] debug_panic" + if rcv := output.String(); !strings.Contains(rcv, expected) { + t.Errorf("Expected %+v, received %+v", expected, rcv) + } + } + + log.SetOutput(os.Stderr) +} + +func TestWriteLogger(t *testing.T) { + log.SetOutput(os.Stderr) + + loggertype := MetaSysLog + id := "id_write" + if err := Newlogger(loggertype, id); err != nil { + t.Error(err) + } + + newWriter, err := syslog.New(syslog.LOG_INFO|syslog.LOG_DAEMON, "CGRates id_write") + if err != nil { + t.Error(err) + } + newLogger := new(StdLogger) + newLogger.SetSyslog(newWriter) + + if n, err := newLogger.Write([]byte(EmptyString)); err != nil { + t.Error(err) + } else if n != 1 { + t.Errorf("Expected 1, received %+v", n) + } + + log.SetOutput(os.Stderr) +} + +func TestCloseLogger(t *testing.T) { + log.SetOutput(ioutil.Discard) + + loggertype := MetaStdLog + if err := Newlogger(loggertype, EmptyString); err != nil { + t.Error(err) + } + + newLogger := new(StdLogger) + if err := newLogger.Close(); err != nil { + t.Error(err) + } + newWriter, err := syslog.New(0, "CGRates") + if err != nil { + t.Error(err) + } + x := newLogger.GetSyslog() + x = newWriter + + newLogger.SetSyslog(x) + if err := newLogger.Close(); err != nil { + t.Error(err) + } +} + +func TestLogStackLogger(t *testing.T) { + LogStack() +} + +func TestNewLoggerInvalidLoggerType(t *testing.T) { + log.SetOutput(ioutil.Discard) + + loggertype := "Invalid_TYPE" + expected := "unsuported logger: " + if err := Newlogger(loggertype, EmptyString); err == nil || err.Error() != expected { + t.Errorf("Expected %+v, received %+v", expected, err) + } +}