package accesslog import ( "fmt" "io/ioutil" "net/http" "net/url" "os" "path/filepath" "testing" shellwords "github.com/mattn/go-shellwords" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type logtestResponseWriter struct{} var ( logger *LogHandler logfileNameSuffix = "/traefik/logger/test.log" helloWorld = "Hello, World" testBackendName = "http://127.0.0.1/testBackend" testFrontendName = "testFrontend" testStatus = 123 testContentSize int64 = 12 testHostname = "TestHost" testUsername = "TestUser" testPath = "testpath" testPort = 8181 testProto = "HTTP/0.0" testMethod = "POST" testReferer = "testReferer" testUserAgent = "testUserAgent" ) func TestLogger(t *testing.T) { tmp, err := ioutil.TempDir("", "testlogger") if err != nil { t.Fatalf("failed to create temp dir: %s", err) } defer os.RemoveAll(tmp) logfilePath := filepath.Join(tmp, logfileNameSuffix) logger, err = NewLogHandler(logfilePath) require.NoError(t, err) defer logger.Close() if _, err := os.Stat(logfilePath); os.IsNotExist(err) { t.Fatalf("logger should create %s", logfilePath) } req := &http.Request{ Header: map[string][]string{ "User-Agent": {testUserAgent}, "Referer": {testReferer}, }, Proto: testProto, Host: testHostname, Method: testMethod, RemoteAddr: fmt.Sprintf("%s:%d", testHostname, testPort), URL: &url.URL{ User: url.UserPassword(testUsername, ""), Path: testPath, }, } logger.ServeHTTP(&logtestResponseWriter{}, req, LogWriterTestHandlerFunc) if logdata, err := ioutil.ReadFile(logfilePath); err != nil { fmt.Printf("%s\n%s\n", string(logdata), err.Error()) assert.NoError(t, err) } else if tokens, err := shellwords.Parse(string(logdata)); err != nil { fmt.Printf("%s\n", err.Error()) assert.NoError(t, err) } else if assert.Equal(t, 14, len(tokens), printLogdata(logdata)) { assert.Equal(t, testHostname, tokens[0], printLogdata(logdata)) assert.Equal(t, testUsername, tokens[2], printLogdata(logdata)) assert.Equal(t, fmt.Sprintf("%s %s %s", testMethod, testPath, testProto), tokens[5], printLogdata(logdata)) assert.Equal(t, fmt.Sprintf("%d", testStatus), tokens[6], printLogdata(logdata)) assert.Equal(t, fmt.Sprintf("%d", len(helloWorld)), tokens[7], printLogdata(logdata)) assert.Equal(t, testReferer, tokens[8], printLogdata(logdata)) assert.Equal(t, testUserAgent, tokens[9], printLogdata(logdata)) assert.Equal(t, "1", tokens[10], printLogdata(logdata)) assert.Equal(t, testFrontendName, tokens[11], printLogdata(logdata)) assert.Equal(t, testBackendName, tokens[12], printLogdata(logdata)) } } func printLogdata(logdata []byte) string { return fmt.Sprintf( "\nExpected: %s\n"+ "Actual: %s", "TestHost - TestUser [13/Apr/2016:07:14:19 -0700] \"POST testpath HTTP/0.0\" 123 12 \"testReferer\" \"testUserAgent\" 1 \"testFrontend\" \"http://127.0.0.1/testBackend\" 1ms", string(logdata)) } func LogWriterTestHandlerFunc(rw http.ResponseWriter, r *http.Request) { rw.Write([]byte(helloWorld)) rw.WriteHeader(testStatus) logDataTable := GetLogDataTable(r) logDataTable.Core[FrontendName] = testFrontendName logDataTable.Core[BackendURL] = testBackendName logDataTable.Core[OriginStatus] = testStatus logDataTable.Core[OriginContentSize] = testContentSize } func (lrw *logtestResponseWriter) Header() http.Header { return map[string][]string{} } func (lrw *logtestResponseWriter) Write(b []byte) (int, error) { return len(b), nil } func (lrw *logtestResponseWriter) WriteHeader(s int) { }