package syslog // import "github.com/docker/docker/daemon/logger/syslog" import ( "log" "net" "os" "path/filepath" "reflect" "runtime" "strings" "testing" syslog "github.com/RackSec/srslog" ) func functionMatches(expectedFun interface{}, actualFun interface{}) bool { return reflect.ValueOf(expectedFun).Pointer() == reflect.ValueOf(actualFun).Pointer() } func TestParseLogFormat(t *testing.T) { formatter, framer, err := parseLogFormat("rfc5424", "udp") if err != nil || !functionMatches(rfc5424formatterWithAppNameAsTag, formatter) || !functionMatches(syslog.DefaultFramer, framer) { t.Fatal("Failed to parse rfc5424 format", err, formatter, framer) } formatter, framer, err = parseLogFormat("rfc5424", "tcp+tls") if err != nil || !functionMatches(rfc5424formatterWithAppNameAsTag, formatter) || !functionMatches(syslog.RFC5425MessageLengthFramer, framer) { t.Fatal("Failed to parse rfc5424 format", err, formatter, framer) } formatter, framer, err = parseLogFormat("rfc5424micro", "udp") if err != nil || !functionMatches(rfc5424microformatterWithAppNameAsTag, formatter) || !functionMatches(syslog.DefaultFramer, framer) { t.Fatal("Failed to parse rfc5424 (microsecond) format", err, formatter, framer) } formatter, framer, err = parseLogFormat("rfc5424micro", "tcp+tls") if err != nil || !functionMatches(rfc5424microformatterWithAppNameAsTag, formatter) || !functionMatches(syslog.RFC5425MessageLengthFramer, framer) { t.Fatal("Failed to parse rfc5424 (microsecond) format", err, formatter, framer) } formatter, framer, err = parseLogFormat("rfc3164", "") if err != nil || !functionMatches(syslog.RFC3164Formatter, formatter) || !functionMatches(syslog.DefaultFramer, framer) { t.Fatal("Failed to parse rfc3164 format", err, formatter, framer) } formatter, framer, err = parseLogFormat("", "") if err != nil || !functionMatches(syslog.UnixFormatter, formatter) || !functionMatches(syslog.DefaultFramer, framer) { t.Fatal("Failed to parse empty format", err, formatter, framer) } formatter, framer, err = parseLogFormat("invalid", "") if err == nil { t.Fatal("Failed to parse invalid format", err, formatter, framer) } } func TestValidateLogOptEmpty(t *testing.T) { emptyConfig := make(map[string]string) if err := ValidateLogOpt(emptyConfig); err != nil { t.Fatal("Failed to parse empty config", err) } } func TestValidateSyslogAddress(t *testing.T) { const sockPlaceholder = "/TEMPDIR/socket.sock" s, err := os.Create(filepath.Join(t.TempDir(), "socket.sock")) if err != nil { log.Fatal(err) } socketPath := s.Name() _ = s.Close() tests := []struct { address string expectedErr string skipOn string }{ { address: "this is not an uri", expectedErr: "unsupported scheme: ''", }, { address: "corrupted:42", expectedErr: "unsupported scheme: 'corrupted'", }, { address: "unix://" + sockPlaceholder, skipOn: "windows", // doesn't work with unix:// sockets }, { address: "unix:///does_not_exist", expectedErr: "no such file or directory", skipOn: "windows", // error message differs }, { address: "tcp://1.2.3.4", }, { address: "udp://1.2.3.4", }, { address: "http://1.2.3.4", expectedErr: "unsupported scheme: 'http'", }, } for _, tc := range tests { tc := tc if tc.skipOn == runtime.GOOS { continue } t.Run(tc.address, func(t *testing.T) { address := strings.Replace(tc.address, sockPlaceholder, socketPath, 1) err := ValidateLogOpt(map[string]string{"syslog-address": address}) if tc.expectedErr != "" { if err == nil { t.Fatal("expected an error, got nil") } if !strings.Contains(err.Error(), tc.expectedErr) { t.Fatalf("expected error to contain '%s', got: '%s'", tc.expectedErr, err) } } else if err != nil { t.Fatalf("unexpected error: '%s'", err) } }) } } func TestParseAddressDefaultPort(t *testing.T) { _, address, err := parseAddress("tcp://1.2.3.4") if err != nil { t.Fatal(err) } _, port, _ := net.SplitHostPort(address) if port != defaultPort { t.Fatalf("Expected to default to port %s. It used port %s", defaultPort, port) } } func TestValidateSyslogFacility(t *testing.T) { err := ValidateLogOpt(map[string]string{ "syslog-facility": "Invalid facility", }) if err == nil { t.Fatal("Expected error if facility level is invalid") } } func TestValidateLogOptSyslogFormat(t *testing.T) { err := ValidateLogOpt(map[string]string{ "syslog-format": "Invalid format", }) if err == nil { t.Fatal("Expected error if format is invalid") } } func TestValidateLogOpt(t *testing.T) { err := ValidateLogOpt(map[string]string{ "env": "http://127.0.0.1", "env-regex": "abc", "labels": "labelA", "labels-regex": "def", "syslog-address": "udp://1.2.3.4:1111", "syslog-facility": "daemon", "syslog-tls-ca-cert": "/etc/ca-certificates/custom/ca.pem", "syslog-tls-cert": "/etc/ca-certificates/custom/cert.pem", "syslog-tls-key": "/etc/ca-certificates/custom/key.pem", "syslog-tls-skip-verify": "true", "tag": "true", "syslog-format": "rfc3164", }) if err != nil { t.Fatal(err) } err = ValidateLogOpt(map[string]string{ "not-supported-option": "a", }) if err == nil { t.Fatal("Expecting error on unsupported options") } }