github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/daemon/logger/splunk/splunk_test.go (about)

     1  package splunk
     2  
     3  import (
     4  	"compress/gzip"
     5  	"context"
     6  	"fmt"
     7  	"net/http"
     8  	"os"
     9  	"runtime"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/docker/docker/daemon/logger"
    14  	"github.com/gotestyourself/gotestyourself/env"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // Validate options
    19  func TestValidateLogOpt(t *testing.T) {
    20  	err := ValidateLogOpt(map[string]string{
    21  		splunkURLKey:                  "http://127.0.0.1",
    22  		splunkTokenKey:                "2160C7EF-2CE9-4307-A180-F852B99CF417",
    23  		splunkSourceKey:               "mysource",
    24  		splunkSourceTypeKey:           "mysourcetype",
    25  		splunkIndexKey:                "myindex",
    26  		splunkCAPathKey:               "/usr/cert.pem",
    27  		splunkCANameKey:               "ca_name",
    28  		splunkInsecureSkipVerifyKey:   "true",
    29  		splunkFormatKey:               "json",
    30  		splunkVerifyConnectionKey:     "true",
    31  		splunkGzipCompressionKey:      "true",
    32  		splunkGzipCompressionLevelKey: "1",
    33  		envKey:      "a",
    34  		envRegexKey: "^foo",
    35  		labelsKey:   "b",
    36  		tagKey:      "c",
    37  	})
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  
    42  	err = ValidateLogOpt(map[string]string{
    43  		"not-supported-option": "a",
    44  	})
    45  	if err == nil {
    46  		t.Fatal("Expecting error on unsupported options")
    47  	}
    48  }
    49  
    50  // Driver require user to specify required options
    51  func TestNewMissedConfig(t *testing.T) {
    52  	info := logger.Info{
    53  		Config: map[string]string{},
    54  	}
    55  	_, err := New(info)
    56  	if err == nil {
    57  		t.Fatal("Logger driver should fail when no required parameters specified")
    58  	}
    59  }
    60  
    61  // Driver require user to specify splunk-url
    62  func TestNewMissedUrl(t *testing.T) {
    63  	info := logger.Info{
    64  		Config: map[string]string{
    65  			splunkTokenKey: "4642492F-D8BD-47F1-A005-0C08AE4657DF",
    66  		},
    67  	}
    68  	_, err := New(info)
    69  	if err.Error() != "splunk: splunk-url is expected" {
    70  		t.Fatal("Logger driver should fail when no required parameters specified")
    71  	}
    72  }
    73  
    74  // Driver require user to specify splunk-token
    75  func TestNewMissedToken(t *testing.T) {
    76  	info := logger.Info{
    77  		Config: map[string]string{
    78  			splunkURLKey: "http://127.0.0.1:8088",
    79  		},
    80  	}
    81  	_, err := New(info)
    82  	if err.Error() != "splunk: splunk-token is expected" {
    83  		t.Fatal("Logger driver should fail when no required parameters specified")
    84  	}
    85  }
    86  
    87  func TestNewWithProxy(t *testing.T) {
    88  	proxy := "http://proxy.testing:8888"
    89  	reset := env.Patch(t, "HTTP_PROXY", proxy)
    90  	defer reset()
    91  
    92  	// must not be localhost
    93  	splunkURL := "http://example.com:12345"
    94  	logger, err := New(logger.Info{
    95  		Config: map[string]string{
    96  			splunkURLKey:              splunkURL,
    97  			splunkTokenKey:            "token",
    98  			splunkVerifyConnectionKey: "false",
    99  		},
   100  		ContainerID: "containeriid",
   101  	})
   102  	require.NoError(t, err)
   103  	splunkLogger := logger.(*splunkLoggerInline)
   104  
   105  	proxyFunc := splunkLogger.transport.Proxy
   106  	require.NotNil(t, proxyFunc)
   107  
   108  	req, err := http.NewRequest("GET", splunkURL, nil)
   109  	require.NoError(t, err)
   110  
   111  	proxyURL, err := proxyFunc(req)
   112  	require.NoError(t, err)
   113  	require.NotNil(t, proxyURL)
   114  	require.Equal(t, proxy, proxyURL.String())
   115  }
   116  
   117  // Test default settings
   118  func TestDefault(t *testing.T) {
   119  	hec := NewHTTPEventCollectorMock(t)
   120  
   121  	go hec.Serve()
   122  
   123  	info := logger.Info{
   124  		Config: map[string]string{
   125  			splunkURLKey:   hec.URL(),
   126  			splunkTokenKey: hec.token,
   127  		},
   128  		ContainerID:        "containeriid",
   129  		ContainerName:      "container_name",
   130  		ContainerImageID:   "contaimageid",
   131  		ContainerImageName: "container_image_name",
   132  	}
   133  
   134  	hostname, err := info.Hostname()
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	loggerDriver, err := New(info)
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	if loggerDriver.Name() != driverName {
   145  		t.Fatal("Unexpected logger driver name")
   146  	}
   147  
   148  	if !hec.connectionVerified {
   149  		t.Fatal("By default connection should be verified")
   150  	}
   151  
   152  	splunkLoggerDriver, ok := loggerDriver.(*splunkLoggerInline)
   153  	if !ok {
   154  		t.Fatal("Unexpected Splunk Logging Driver type")
   155  	}
   156  
   157  	if splunkLoggerDriver.url != hec.URL()+"/services/collector/event/1.0" ||
   158  		splunkLoggerDriver.auth != "Splunk "+hec.token ||
   159  		splunkLoggerDriver.nullMessage.Host != hostname ||
   160  		splunkLoggerDriver.nullMessage.Source != "" ||
   161  		splunkLoggerDriver.nullMessage.SourceType != "" ||
   162  		splunkLoggerDriver.nullMessage.Index != "" ||
   163  		splunkLoggerDriver.gzipCompression ||
   164  		splunkLoggerDriver.postMessagesFrequency != defaultPostMessagesFrequency ||
   165  		splunkLoggerDriver.postMessagesBatchSize != defaultPostMessagesBatchSize ||
   166  		splunkLoggerDriver.bufferMaximum != defaultBufferMaximum ||
   167  		cap(splunkLoggerDriver.stream) != defaultStreamChannelSize {
   168  		t.Fatal("Found not default values setup in Splunk Logging Driver.")
   169  	}
   170  
   171  	message1Time := time.Now()
   172  	if err := loggerDriver.Log(&logger.Message{Line: []byte("{\"a\":\"b\"}"), Source: "stdout", Timestamp: message1Time}); err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	message2Time := time.Now()
   176  	if err := loggerDriver.Log(&logger.Message{Line: []byte("notajson"), Source: "stdout", Timestamp: message2Time}); err != nil {
   177  		t.Fatal(err)
   178  	}
   179  
   180  	err = loggerDriver.Close()
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	if len(hec.messages) != 2 {
   186  		t.Fatal("Expected two messages")
   187  	}
   188  
   189  	if *hec.gzipEnabled {
   190  		t.Fatal("Gzip should not be used")
   191  	}
   192  
   193  	message1 := hec.messages[0]
   194  	if message1.Time != fmt.Sprintf("%f", float64(message1Time.UnixNano())/float64(time.Second)) ||
   195  		message1.Host != hostname ||
   196  		message1.Source != "" ||
   197  		message1.SourceType != "" ||
   198  		message1.Index != "" {
   199  		t.Fatalf("Unexpected values of message 1 %v", message1)
   200  	}
   201  
   202  	if event, err := message1.EventAsMap(); err != nil {
   203  		t.Fatal(err)
   204  	} else {
   205  		if event["line"] != "{\"a\":\"b\"}" ||
   206  			event["source"] != "stdout" ||
   207  			event["tag"] != "containeriid" ||
   208  			len(event) != 3 {
   209  			t.Fatalf("Unexpected event in message %v", event)
   210  		}
   211  	}
   212  
   213  	message2 := hec.messages[1]
   214  	if message2.Time != fmt.Sprintf("%f", float64(message2Time.UnixNano())/float64(time.Second)) ||
   215  		message2.Host != hostname ||
   216  		message2.Source != "" ||
   217  		message2.SourceType != "" ||
   218  		message2.Index != "" {
   219  		t.Fatalf("Unexpected values of message 1 %v", message2)
   220  	}
   221  
   222  	if event, err := message2.EventAsMap(); err != nil {
   223  		t.Fatal(err)
   224  	} else {
   225  		if event["line"] != "notajson" ||
   226  			event["source"] != "stdout" ||
   227  			event["tag"] != "containeriid" ||
   228  			len(event) != 3 {
   229  			t.Fatalf("Unexpected event in message %v", event)
   230  		}
   231  	}
   232  
   233  	err = hec.Close()
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  }
   238  
   239  // Verify inline format with a not default settings for most of options
   240  func TestInlineFormatWithNonDefaultOptions(t *testing.T) {
   241  	hec := NewHTTPEventCollectorMock(t)
   242  
   243  	go hec.Serve()
   244  
   245  	info := logger.Info{
   246  		Config: map[string]string{
   247  			splunkURLKey:             hec.URL(),
   248  			splunkTokenKey:           hec.token,
   249  			splunkSourceKey:          "mysource",
   250  			splunkSourceTypeKey:      "mysourcetype",
   251  			splunkIndexKey:           "myindex",
   252  			splunkFormatKey:          splunkFormatInline,
   253  			splunkGzipCompressionKey: "true",
   254  			tagKey:      "{{.ImageName}}/{{.Name}}",
   255  			labelsKey:   "a",
   256  			envRegexKey: "^foo",
   257  		},
   258  		ContainerID:        "containeriid",
   259  		ContainerName:      "/container_name",
   260  		ContainerImageID:   "contaimageid",
   261  		ContainerImageName: "container_image_name",
   262  		ContainerLabels: map[string]string{
   263  			"a": "b",
   264  		},
   265  		ContainerEnv: []string{"foo_finder=bar"},
   266  	}
   267  
   268  	hostname, err := info.Hostname()
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  
   273  	loggerDriver, err := New(info)
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  
   278  	if !hec.connectionVerified {
   279  		t.Fatal("By default connection should be verified")
   280  	}
   281  
   282  	splunkLoggerDriver, ok := loggerDriver.(*splunkLoggerInline)
   283  	if !ok {
   284  		t.Fatal("Unexpected Splunk Logging Driver type")
   285  	}
   286  
   287  	if splunkLoggerDriver.url != hec.URL()+"/services/collector/event/1.0" ||
   288  		splunkLoggerDriver.auth != "Splunk "+hec.token ||
   289  		splunkLoggerDriver.nullMessage.Host != hostname ||
   290  		splunkLoggerDriver.nullMessage.Source != "mysource" ||
   291  		splunkLoggerDriver.nullMessage.SourceType != "mysourcetype" ||
   292  		splunkLoggerDriver.nullMessage.Index != "myindex" ||
   293  		!splunkLoggerDriver.gzipCompression ||
   294  		splunkLoggerDriver.gzipCompressionLevel != gzip.DefaultCompression ||
   295  		splunkLoggerDriver.postMessagesFrequency != defaultPostMessagesFrequency ||
   296  		splunkLoggerDriver.postMessagesBatchSize != defaultPostMessagesBatchSize ||
   297  		splunkLoggerDriver.bufferMaximum != defaultBufferMaximum ||
   298  		cap(splunkLoggerDriver.stream) != defaultStreamChannelSize {
   299  		t.Fatal("Values do not match configuration.")
   300  	}
   301  
   302  	messageTime := time.Now()
   303  	if err := loggerDriver.Log(&logger.Message{Line: []byte("1"), Source: "stdout", Timestamp: messageTime}); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  
   307  	err = loggerDriver.Close()
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	if len(hec.messages) != 1 {
   313  		t.Fatal("Expected one message")
   314  	}
   315  
   316  	if !*hec.gzipEnabled {
   317  		t.Fatal("Gzip should be used")
   318  	}
   319  
   320  	message := hec.messages[0]
   321  	if message.Time != fmt.Sprintf("%f", float64(messageTime.UnixNano())/float64(time.Second)) ||
   322  		message.Host != hostname ||
   323  		message.Source != "mysource" ||
   324  		message.SourceType != "mysourcetype" ||
   325  		message.Index != "myindex" {
   326  		t.Fatalf("Unexpected values of message %v", message)
   327  	}
   328  
   329  	if event, err := message.EventAsMap(); err != nil {
   330  		t.Fatal(err)
   331  	} else {
   332  		if event["line"] != "1" ||
   333  			event["source"] != "stdout" ||
   334  			event["tag"] != "container_image_name/container_name" ||
   335  			event["attrs"].(map[string]interface{})["a"] != "b" ||
   336  			event["attrs"].(map[string]interface{})["foo_finder"] != "bar" ||
   337  			len(event) != 4 {
   338  			t.Fatalf("Unexpected event in message %v", event)
   339  		}
   340  	}
   341  
   342  	err = hec.Close()
   343  	if err != nil {
   344  		t.Fatal(err)
   345  	}
   346  }
   347  
   348  // Verify JSON format
   349  func TestJsonFormat(t *testing.T) {
   350  	hec := NewHTTPEventCollectorMock(t)
   351  
   352  	go hec.Serve()
   353  
   354  	info := logger.Info{
   355  		Config: map[string]string{
   356  			splunkURLKey:                  hec.URL(),
   357  			splunkTokenKey:                hec.token,
   358  			splunkFormatKey:               splunkFormatJSON,
   359  			splunkGzipCompressionKey:      "true",
   360  			splunkGzipCompressionLevelKey: "1",
   361  		},
   362  		ContainerID:        "containeriid",
   363  		ContainerName:      "/container_name",
   364  		ContainerImageID:   "contaimageid",
   365  		ContainerImageName: "container_image_name",
   366  	}
   367  
   368  	hostname, err := info.Hostname()
   369  	if err != nil {
   370  		t.Fatal(err)
   371  	}
   372  
   373  	loggerDriver, err := New(info)
   374  	if err != nil {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	if !hec.connectionVerified {
   379  		t.Fatal("By default connection should be verified")
   380  	}
   381  
   382  	splunkLoggerDriver, ok := loggerDriver.(*splunkLoggerJSON)
   383  	if !ok {
   384  		t.Fatal("Unexpected Splunk Logging Driver type")
   385  	}
   386  
   387  	if splunkLoggerDriver.url != hec.URL()+"/services/collector/event/1.0" ||
   388  		splunkLoggerDriver.auth != "Splunk "+hec.token ||
   389  		splunkLoggerDriver.nullMessage.Host != hostname ||
   390  		splunkLoggerDriver.nullMessage.Source != "" ||
   391  		splunkLoggerDriver.nullMessage.SourceType != "" ||
   392  		splunkLoggerDriver.nullMessage.Index != "" ||
   393  		!splunkLoggerDriver.gzipCompression ||
   394  		splunkLoggerDriver.gzipCompressionLevel != gzip.BestSpeed ||
   395  		splunkLoggerDriver.postMessagesFrequency != defaultPostMessagesFrequency ||
   396  		splunkLoggerDriver.postMessagesBatchSize != defaultPostMessagesBatchSize ||
   397  		splunkLoggerDriver.bufferMaximum != defaultBufferMaximum ||
   398  		cap(splunkLoggerDriver.stream) != defaultStreamChannelSize {
   399  		t.Fatal("Values do not match configuration.")
   400  	}
   401  
   402  	message1Time := time.Now()
   403  	if err := loggerDriver.Log(&logger.Message{Line: []byte("{\"a\":\"b\"}"), Source: "stdout", Timestamp: message1Time}); err != nil {
   404  		t.Fatal(err)
   405  	}
   406  	message2Time := time.Now()
   407  	if err := loggerDriver.Log(&logger.Message{Line: []byte("notjson"), Source: "stdout", Timestamp: message2Time}); err != nil {
   408  		t.Fatal(err)
   409  	}
   410  
   411  	err = loggerDriver.Close()
   412  	if err != nil {
   413  		t.Fatal(err)
   414  	}
   415  
   416  	if len(hec.messages) != 2 {
   417  		t.Fatal("Expected two messages")
   418  	}
   419  
   420  	message1 := hec.messages[0]
   421  	if message1.Time != fmt.Sprintf("%f", float64(message1Time.UnixNano())/float64(time.Second)) ||
   422  		message1.Host != hostname ||
   423  		message1.Source != "" ||
   424  		message1.SourceType != "" ||
   425  		message1.Index != "" {
   426  		t.Fatalf("Unexpected values of message 1 %v", message1)
   427  	}
   428  
   429  	if event, err := message1.EventAsMap(); err != nil {
   430  		t.Fatal(err)
   431  	} else {
   432  		if event["line"].(map[string]interface{})["a"] != "b" ||
   433  			event["source"] != "stdout" ||
   434  			event["tag"] != "containeriid" ||
   435  			len(event) != 3 {
   436  			t.Fatalf("Unexpected event in message 1 %v", event)
   437  		}
   438  	}
   439  
   440  	message2 := hec.messages[1]
   441  	if message2.Time != fmt.Sprintf("%f", float64(message2Time.UnixNano())/float64(time.Second)) ||
   442  		message2.Host != hostname ||
   443  		message2.Source != "" ||
   444  		message2.SourceType != "" ||
   445  		message2.Index != "" {
   446  		t.Fatalf("Unexpected values of message 2 %v", message2)
   447  	}
   448  
   449  	// If message cannot be parsed as JSON - it should be sent as a line
   450  	if event, err := message2.EventAsMap(); err != nil {
   451  		t.Fatal(err)
   452  	} else {
   453  		if event["line"] != "notjson" ||
   454  			event["source"] != "stdout" ||
   455  			event["tag"] != "containeriid" ||
   456  			len(event) != 3 {
   457  			t.Fatalf("Unexpected event in message 2 %v", event)
   458  		}
   459  	}
   460  
   461  	err = hec.Close()
   462  	if err != nil {
   463  		t.Fatal(err)
   464  	}
   465  }
   466  
   467  // Verify raw format
   468  func TestRawFormat(t *testing.T) {
   469  	hec := NewHTTPEventCollectorMock(t)
   470  
   471  	go hec.Serve()
   472  
   473  	info := logger.Info{
   474  		Config: map[string]string{
   475  			splunkURLKey:    hec.URL(),
   476  			splunkTokenKey:  hec.token,
   477  			splunkFormatKey: splunkFormatRaw,
   478  		},
   479  		ContainerID:        "containeriid",
   480  		ContainerName:      "/container_name",
   481  		ContainerImageID:   "contaimageid",
   482  		ContainerImageName: "container_image_name",
   483  	}
   484  
   485  	hostname, err := info.Hostname()
   486  	require.NoError(t, err)
   487  
   488  	loggerDriver, err := New(info)
   489  	require.NoError(t, err)
   490  
   491  	if !hec.connectionVerified {
   492  		t.Fatal("By default connection should be verified")
   493  	}
   494  
   495  	splunkLoggerDriver, ok := loggerDriver.(*splunkLoggerRaw)
   496  	if !ok {
   497  		t.Fatal("Unexpected Splunk Logging Driver type")
   498  	}
   499  
   500  	if splunkLoggerDriver.url != hec.URL()+"/services/collector/event/1.0" ||
   501  		splunkLoggerDriver.auth != "Splunk "+hec.token ||
   502  		splunkLoggerDriver.nullMessage.Host != hostname ||
   503  		splunkLoggerDriver.nullMessage.Source != "" ||
   504  		splunkLoggerDriver.nullMessage.SourceType != "" ||
   505  		splunkLoggerDriver.nullMessage.Index != "" ||
   506  		splunkLoggerDriver.gzipCompression ||
   507  		splunkLoggerDriver.postMessagesFrequency != defaultPostMessagesFrequency ||
   508  		splunkLoggerDriver.postMessagesBatchSize != defaultPostMessagesBatchSize ||
   509  		splunkLoggerDriver.bufferMaximum != defaultBufferMaximum ||
   510  		cap(splunkLoggerDriver.stream) != defaultStreamChannelSize ||
   511  		string(splunkLoggerDriver.prefix) != "containeriid " {
   512  		t.Fatal("Values do not match configuration.")
   513  	}
   514  
   515  	message1Time := time.Now()
   516  	if err := loggerDriver.Log(&logger.Message{Line: []byte("{\"a\":\"b\"}"), Source: "stdout", Timestamp: message1Time}); err != nil {
   517  		t.Fatal(err)
   518  	}
   519  	message2Time := time.Now()
   520  	if err := loggerDriver.Log(&logger.Message{Line: []byte("notjson"), Source: "stdout", Timestamp: message2Time}); err != nil {
   521  		t.Fatal(err)
   522  	}
   523  
   524  	err = loggerDriver.Close()
   525  	if err != nil {
   526  		t.Fatal(err)
   527  	}
   528  
   529  	if len(hec.messages) != 2 {
   530  		t.Fatal("Expected two messages")
   531  	}
   532  
   533  	message1 := hec.messages[0]
   534  	if message1.Time != fmt.Sprintf("%f", float64(message1Time.UnixNano())/float64(time.Second)) ||
   535  		message1.Host != hostname ||
   536  		message1.Source != "" ||
   537  		message1.SourceType != "" ||
   538  		message1.Index != "" {
   539  		t.Fatalf("Unexpected values of message 1 %v", message1)
   540  	}
   541  
   542  	if event, err := message1.EventAsString(); err != nil {
   543  		t.Fatal(err)
   544  	} else {
   545  		if event != "containeriid {\"a\":\"b\"}" {
   546  			t.Fatalf("Unexpected event in message 1 %v", event)
   547  		}
   548  	}
   549  
   550  	message2 := hec.messages[1]
   551  	if message2.Time != fmt.Sprintf("%f", float64(message2Time.UnixNano())/float64(time.Second)) ||
   552  		message2.Host != hostname ||
   553  		message2.Source != "" ||
   554  		message2.SourceType != "" ||
   555  		message2.Index != "" {
   556  		t.Fatalf("Unexpected values of message 2 %v", message2)
   557  	}
   558  
   559  	if event, err := message2.EventAsString(); err != nil {
   560  		t.Fatal(err)
   561  	} else {
   562  		if event != "containeriid notjson" {
   563  			t.Fatalf("Unexpected event in message 1 %v", event)
   564  		}
   565  	}
   566  
   567  	err = hec.Close()
   568  	if err != nil {
   569  		t.Fatal(err)
   570  	}
   571  }
   572  
   573  // Verify raw format with labels
   574  func TestRawFormatWithLabels(t *testing.T) {
   575  	hec := NewHTTPEventCollectorMock(t)
   576  
   577  	go hec.Serve()
   578  
   579  	info := logger.Info{
   580  		Config: map[string]string{
   581  			splunkURLKey:    hec.URL(),
   582  			splunkTokenKey:  hec.token,
   583  			splunkFormatKey: splunkFormatRaw,
   584  			labelsKey:       "a",
   585  		},
   586  		ContainerID:        "containeriid",
   587  		ContainerName:      "/container_name",
   588  		ContainerImageID:   "contaimageid",
   589  		ContainerImageName: "container_image_name",
   590  		ContainerLabels: map[string]string{
   591  			"a": "b",
   592  		},
   593  	}
   594  
   595  	hostname, err := info.Hostname()
   596  	if err != nil {
   597  		t.Fatal(err)
   598  	}
   599  
   600  	loggerDriver, err := New(info)
   601  	if err != nil {
   602  		t.Fatal(err)
   603  	}
   604  
   605  	if !hec.connectionVerified {
   606  		t.Fatal("By default connection should be verified")
   607  	}
   608  
   609  	splunkLoggerDriver, ok := loggerDriver.(*splunkLoggerRaw)
   610  	if !ok {
   611  		t.Fatal("Unexpected Splunk Logging Driver type")
   612  	}
   613  
   614  	if splunkLoggerDriver.url != hec.URL()+"/services/collector/event/1.0" ||
   615  		splunkLoggerDriver.auth != "Splunk "+hec.token ||
   616  		splunkLoggerDriver.nullMessage.Host != hostname ||
   617  		splunkLoggerDriver.nullMessage.Source != "" ||
   618  		splunkLoggerDriver.nullMessage.SourceType != "" ||
   619  		splunkLoggerDriver.nullMessage.Index != "" ||
   620  		splunkLoggerDriver.gzipCompression ||
   621  		splunkLoggerDriver.postMessagesFrequency != defaultPostMessagesFrequency ||
   622  		splunkLoggerDriver.postMessagesBatchSize != defaultPostMessagesBatchSize ||
   623  		splunkLoggerDriver.bufferMaximum != defaultBufferMaximum ||
   624  		cap(splunkLoggerDriver.stream) != defaultStreamChannelSize ||
   625  		string(splunkLoggerDriver.prefix) != "containeriid a=b " {
   626  		t.Fatal("Values do not match configuration.")
   627  	}
   628  
   629  	message1Time := time.Now()
   630  	if err := loggerDriver.Log(&logger.Message{Line: []byte("{\"a\":\"b\"}"), Source: "stdout", Timestamp: message1Time}); err != nil {
   631  		t.Fatal(err)
   632  	}
   633  	message2Time := time.Now()
   634  	if err := loggerDriver.Log(&logger.Message{Line: []byte("notjson"), Source: "stdout", Timestamp: message2Time}); err != nil {
   635  		t.Fatal(err)
   636  	}
   637  
   638  	err = loggerDriver.Close()
   639  	if err != nil {
   640  		t.Fatal(err)
   641  	}
   642  
   643  	if len(hec.messages) != 2 {
   644  		t.Fatal("Expected two messages")
   645  	}
   646  
   647  	message1 := hec.messages[0]
   648  	if message1.Time != fmt.Sprintf("%f", float64(message1Time.UnixNano())/float64(time.Second)) ||
   649  		message1.Host != hostname ||
   650  		message1.Source != "" ||
   651  		message1.SourceType != "" ||
   652  		message1.Index != "" {
   653  		t.Fatalf("Unexpected values of message 1 %v", message1)
   654  	}
   655  
   656  	if event, err := message1.EventAsString(); err != nil {
   657  		t.Fatal(err)
   658  	} else {
   659  		if event != "containeriid a=b {\"a\":\"b\"}" {
   660  			t.Fatalf("Unexpected event in message 1 %v", event)
   661  		}
   662  	}
   663  
   664  	message2 := hec.messages[1]
   665  	if message2.Time != fmt.Sprintf("%f", float64(message2Time.UnixNano())/float64(time.Second)) ||
   666  		message2.Host != hostname ||
   667  		message2.Source != "" ||
   668  		message2.SourceType != "" ||
   669  		message2.Index != "" {
   670  		t.Fatalf("Unexpected values of message 2 %v", message2)
   671  	}
   672  
   673  	if event, err := message2.EventAsString(); err != nil {
   674  		t.Fatal(err)
   675  	} else {
   676  		if event != "containeriid a=b notjson" {
   677  			t.Fatalf("Unexpected event in message 2 %v", event)
   678  		}
   679  	}
   680  
   681  	err = hec.Close()
   682  	if err != nil {
   683  		t.Fatal(err)
   684  	}
   685  }
   686  
   687  // Verify that Splunk Logging Driver can accept tag="" which will allow to send raw messages
   688  // in the same way we get them in stdout/stderr
   689  func TestRawFormatWithoutTag(t *testing.T) {
   690  	hec := NewHTTPEventCollectorMock(t)
   691  
   692  	go hec.Serve()
   693  
   694  	info := logger.Info{
   695  		Config: map[string]string{
   696  			splunkURLKey:    hec.URL(),
   697  			splunkTokenKey:  hec.token,
   698  			splunkFormatKey: splunkFormatRaw,
   699  			tagKey:          "",
   700  		},
   701  		ContainerID:        "containeriid",
   702  		ContainerName:      "/container_name",
   703  		ContainerImageID:   "contaimageid",
   704  		ContainerImageName: "container_image_name",
   705  	}
   706  
   707  	hostname, err := info.Hostname()
   708  	if err != nil {
   709  		t.Fatal(err)
   710  	}
   711  
   712  	loggerDriver, err := New(info)
   713  	if err != nil {
   714  		t.Fatal(err)
   715  	}
   716  
   717  	if !hec.connectionVerified {
   718  		t.Fatal("By default connection should be verified")
   719  	}
   720  
   721  	splunkLoggerDriver, ok := loggerDriver.(*splunkLoggerRaw)
   722  	if !ok {
   723  		t.Fatal("Unexpected Splunk Logging Driver type")
   724  	}
   725  
   726  	if splunkLoggerDriver.url != hec.URL()+"/services/collector/event/1.0" ||
   727  		splunkLoggerDriver.auth != "Splunk "+hec.token ||
   728  		splunkLoggerDriver.nullMessage.Host != hostname ||
   729  		splunkLoggerDriver.nullMessage.Source != "" ||
   730  		splunkLoggerDriver.nullMessage.SourceType != "" ||
   731  		splunkLoggerDriver.nullMessage.Index != "" ||
   732  		splunkLoggerDriver.gzipCompression ||
   733  		splunkLoggerDriver.postMessagesFrequency != defaultPostMessagesFrequency ||
   734  		splunkLoggerDriver.postMessagesBatchSize != defaultPostMessagesBatchSize ||
   735  		splunkLoggerDriver.bufferMaximum != defaultBufferMaximum ||
   736  		cap(splunkLoggerDriver.stream) != defaultStreamChannelSize ||
   737  		string(splunkLoggerDriver.prefix) != "" {
   738  		t.Log(string(splunkLoggerDriver.prefix) + "a")
   739  		t.Fatal("Values do not match configuration.")
   740  	}
   741  
   742  	message1Time := time.Now()
   743  	if err := loggerDriver.Log(&logger.Message{Line: []byte("{\"a\":\"b\"}"), Source: "stdout", Timestamp: message1Time}); err != nil {
   744  		t.Fatal(err)
   745  	}
   746  	message2Time := time.Now()
   747  	if err := loggerDriver.Log(&logger.Message{Line: []byte("notjson"), Source: "stdout", Timestamp: message2Time}); err != nil {
   748  		t.Fatal(err)
   749  	}
   750  	message3Time := time.Now()
   751  	if err := loggerDriver.Log(&logger.Message{Line: []byte(" "), Source: "stdout", Timestamp: message3Time}); err != nil {
   752  		t.Fatal(err)
   753  	}
   754  
   755  	err = loggerDriver.Close()
   756  	if err != nil {
   757  		t.Fatal(err)
   758  	}
   759  
   760  	// message3 would have an empty or whitespace only string in the "event" field
   761  	// both of which are not acceptable to HEC
   762  	// thus here we must expect 2 messages, not 3
   763  	if len(hec.messages) != 2 {
   764  		t.Fatal("Expected two messages")
   765  	}
   766  
   767  	message1 := hec.messages[0]
   768  	if message1.Time != fmt.Sprintf("%f", float64(message1Time.UnixNano())/float64(time.Second)) ||
   769  		message1.Host != hostname ||
   770  		message1.Source != "" ||
   771  		message1.SourceType != "" ||
   772  		message1.Index != "" {
   773  		t.Fatalf("Unexpected values of message 1 %v", message1)
   774  	}
   775  
   776  	if event, err := message1.EventAsString(); err != nil {
   777  		t.Fatal(err)
   778  	} else {
   779  		if event != "{\"a\":\"b\"}" {
   780  			t.Fatalf("Unexpected event in message 1 %v", event)
   781  		}
   782  	}
   783  
   784  	message2 := hec.messages[1]
   785  	if message2.Time != fmt.Sprintf("%f", float64(message2Time.UnixNano())/float64(time.Second)) ||
   786  		message2.Host != hostname ||
   787  		message2.Source != "" ||
   788  		message2.SourceType != "" ||
   789  		message2.Index != "" {
   790  		t.Fatalf("Unexpected values of message 2 %v", message2)
   791  	}
   792  
   793  	if event, err := message2.EventAsString(); err != nil {
   794  		t.Fatal(err)
   795  	} else {
   796  		if event != "notjson" {
   797  			t.Fatalf("Unexpected event in message 2 %v", event)
   798  		}
   799  	}
   800  
   801  	err = hec.Close()
   802  	if err != nil {
   803  		t.Fatal(err)
   804  	}
   805  }
   806  
   807  // Verify that we will send messages in batches with default batching parameters,
   808  // but change frequency to be sure that numOfRequests will match expected 17 requests
   809  func TestBatching(t *testing.T) {
   810  	if err := os.Setenv(envVarPostMessagesFrequency, "10h"); err != nil {
   811  		t.Fatal(err)
   812  	}
   813  
   814  	hec := NewHTTPEventCollectorMock(t)
   815  
   816  	go hec.Serve()
   817  
   818  	info := logger.Info{
   819  		Config: map[string]string{
   820  			splunkURLKey:   hec.URL(),
   821  			splunkTokenKey: hec.token,
   822  		},
   823  		ContainerID:        "containeriid",
   824  		ContainerName:      "/container_name",
   825  		ContainerImageID:   "contaimageid",
   826  		ContainerImageName: "container_image_name",
   827  	}
   828  
   829  	loggerDriver, err := New(info)
   830  	if err != nil {
   831  		t.Fatal(err)
   832  	}
   833  
   834  	for i := 0; i < defaultStreamChannelSize*4; i++ {
   835  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
   836  			t.Fatal(err)
   837  		}
   838  	}
   839  
   840  	err = loggerDriver.Close()
   841  	if err != nil {
   842  		t.Fatal(err)
   843  	}
   844  
   845  	if len(hec.messages) != defaultStreamChannelSize*4 {
   846  		t.Fatal("Not all messages delivered")
   847  	}
   848  
   849  	for i, message := range hec.messages {
   850  		if event, err := message.EventAsMap(); err != nil {
   851  			t.Fatal(err)
   852  		} else {
   853  			if event["line"] != fmt.Sprintf("%d", i) {
   854  				t.Fatalf("Unexpected event in message %v", event)
   855  			}
   856  		}
   857  	}
   858  
   859  	// 1 to verify connection and 16 batches
   860  	if hec.numOfRequests != 17 {
   861  		t.Fatalf("Unexpected number of requests %d", hec.numOfRequests)
   862  	}
   863  
   864  	err = hec.Close()
   865  	if err != nil {
   866  		t.Fatal(err)
   867  	}
   868  
   869  	if err := os.Setenv(envVarPostMessagesFrequency, ""); err != nil {
   870  		t.Fatal(err)
   871  	}
   872  }
   873  
   874  // Verify that test is using time to fire events not rare than specified frequency
   875  func TestFrequency(t *testing.T) {
   876  	if err := os.Setenv(envVarPostMessagesFrequency, "5ms"); err != nil {
   877  		t.Fatal(err)
   878  	}
   879  
   880  	hec := NewHTTPEventCollectorMock(t)
   881  
   882  	go hec.Serve()
   883  
   884  	info := logger.Info{
   885  		Config: map[string]string{
   886  			splunkURLKey:   hec.URL(),
   887  			splunkTokenKey: hec.token,
   888  		},
   889  		ContainerID:        "containeriid",
   890  		ContainerName:      "/container_name",
   891  		ContainerImageID:   "contaimageid",
   892  		ContainerImageName: "container_image_name",
   893  	}
   894  
   895  	loggerDriver, err := New(info)
   896  	if err != nil {
   897  		t.Fatal(err)
   898  	}
   899  
   900  	for i := 0; i < 10; i++ {
   901  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
   902  			t.Fatal(err)
   903  		}
   904  		time.Sleep(15 * time.Millisecond)
   905  	}
   906  
   907  	err = loggerDriver.Close()
   908  	if err != nil {
   909  		t.Fatal(err)
   910  	}
   911  
   912  	if len(hec.messages) != 10 {
   913  		t.Fatal("Not all messages delivered")
   914  	}
   915  
   916  	for i, message := range hec.messages {
   917  		if event, err := message.EventAsMap(); err != nil {
   918  			t.Fatal(err)
   919  		} else {
   920  			if event["line"] != fmt.Sprintf("%d", i) {
   921  				t.Fatalf("Unexpected event in message %v", event)
   922  			}
   923  		}
   924  	}
   925  
   926  	// 1 to verify connection and 10 to verify that we have sent messages with required frequency,
   927  	// but because frequency is too small (to keep test quick), instead of 11, use 9 if context switches will be slow
   928  	if hec.numOfRequests < 9 {
   929  		t.Fatalf("Unexpected number of requests %d", hec.numOfRequests)
   930  	}
   931  
   932  	err = hec.Close()
   933  	if err != nil {
   934  		t.Fatal(err)
   935  	}
   936  
   937  	if err := os.Setenv(envVarPostMessagesFrequency, ""); err != nil {
   938  		t.Fatal(err)
   939  	}
   940  }
   941  
   942  // Simulate behavior similar to first version of Splunk Logging Driver, when we were sending one message
   943  // per request
   944  func TestOneMessagePerRequest(t *testing.T) {
   945  	if err := os.Setenv(envVarPostMessagesFrequency, "10h"); err != nil {
   946  		t.Fatal(err)
   947  	}
   948  
   949  	if err := os.Setenv(envVarPostMessagesBatchSize, "1"); err != nil {
   950  		t.Fatal(err)
   951  	}
   952  
   953  	if err := os.Setenv(envVarBufferMaximum, "1"); err != nil {
   954  		t.Fatal(err)
   955  	}
   956  
   957  	if err := os.Setenv(envVarStreamChannelSize, "0"); err != nil {
   958  		t.Fatal(err)
   959  	}
   960  
   961  	hec := NewHTTPEventCollectorMock(t)
   962  
   963  	go hec.Serve()
   964  
   965  	info := logger.Info{
   966  		Config: map[string]string{
   967  			splunkURLKey:   hec.URL(),
   968  			splunkTokenKey: hec.token,
   969  		},
   970  		ContainerID:        "containeriid",
   971  		ContainerName:      "/container_name",
   972  		ContainerImageID:   "contaimageid",
   973  		ContainerImageName: "container_image_name",
   974  	}
   975  
   976  	loggerDriver, err := New(info)
   977  	if err != nil {
   978  		t.Fatal(err)
   979  	}
   980  
   981  	for i := 0; i < 10; i++ {
   982  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
   983  			t.Fatal(err)
   984  		}
   985  	}
   986  
   987  	err = loggerDriver.Close()
   988  	if err != nil {
   989  		t.Fatal(err)
   990  	}
   991  
   992  	if len(hec.messages) != 10 {
   993  		t.Fatal("Not all messages delivered")
   994  	}
   995  
   996  	for i, message := range hec.messages {
   997  		if event, err := message.EventAsMap(); err != nil {
   998  			t.Fatal(err)
   999  		} else {
  1000  			if event["line"] != fmt.Sprintf("%d", i) {
  1001  				t.Fatalf("Unexpected event in message %v", event)
  1002  			}
  1003  		}
  1004  	}
  1005  
  1006  	// 1 to verify connection and 10 messages
  1007  	if hec.numOfRequests != 11 {
  1008  		t.Fatalf("Unexpected number of requests %d", hec.numOfRequests)
  1009  	}
  1010  
  1011  	err = hec.Close()
  1012  	if err != nil {
  1013  		t.Fatal(err)
  1014  	}
  1015  
  1016  	if err := os.Setenv(envVarPostMessagesFrequency, ""); err != nil {
  1017  		t.Fatal(err)
  1018  	}
  1019  
  1020  	if err := os.Setenv(envVarPostMessagesBatchSize, ""); err != nil {
  1021  		t.Fatal(err)
  1022  	}
  1023  
  1024  	if err := os.Setenv(envVarBufferMaximum, ""); err != nil {
  1025  		t.Fatal(err)
  1026  	}
  1027  
  1028  	if err := os.Setenv(envVarStreamChannelSize, ""); err != nil {
  1029  		t.Fatal(err)
  1030  	}
  1031  }
  1032  
  1033  // Driver should not be created when HEC is unresponsive
  1034  func TestVerify(t *testing.T) {
  1035  	hec := NewHTTPEventCollectorMock(t)
  1036  	hec.simulateServerError = true
  1037  	go hec.Serve()
  1038  
  1039  	info := logger.Info{
  1040  		Config: map[string]string{
  1041  			splunkURLKey:   hec.URL(),
  1042  			splunkTokenKey: hec.token,
  1043  		},
  1044  		ContainerID:        "containeriid",
  1045  		ContainerName:      "/container_name",
  1046  		ContainerImageID:   "contaimageid",
  1047  		ContainerImageName: "container_image_name",
  1048  	}
  1049  
  1050  	_, err := New(info)
  1051  	if err == nil {
  1052  		t.Fatal("Expecting driver to fail, when server is unresponsive")
  1053  	}
  1054  
  1055  	err = hec.Close()
  1056  	if err != nil {
  1057  		t.Fatal(err)
  1058  	}
  1059  }
  1060  
  1061  // Verify that user can specify to skip verification that Splunk HEC is working.
  1062  // Also in this test we verify retry logic.
  1063  func TestSkipVerify(t *testing.T) {
  1064  	hec := NewHTTPEventCollectorMock(t)
  1065  	hec.simulateServerError = true
  1066  	go hec.Serve()
  1067  
  1068  	info := logger.Info{
  1069  		Config: map[string]string{
  1070  			splunkURLKey:              hec.URL(),
  1071  			splunkTokenKey:            hec.token,
  1072  			splunkVerifyConnectionKey: "false",
  1073  		},
  1074  		ContainerID:        "containeriid",
  1075  		ContainerName:      "/container_name",
  1076  		ContainerImageID:   "contaimageid",
  1077  		ContainerImageName: "container_image_name",
  1078  	}
  1079  
  1080  	loggerDriver, err := New(info)
  1081  	if err != nil {
  1082  		t.Fatal(err)
  1083  	}
  1084  
  1085  	if hec.connectionVerified {
  1086  		t.Fatal("Connection should not be verified")
  1087  	}
  1088  
  1089  	for i := 0; i < defaultStreamChannelSize*2; i++ {
  1090  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1091  			t.Fatal(err)
  1092  		}
  1093  	}
  1094  
  1095  	if len(hec.messages) != 0 {
  1096  		t.Fatal("No messages should be accepted at this point")
  1097  	}
  1098  
  1099  	hec.simulateErr(false)
  1100  
  1101  	for i := defaultStreamChannelSize * 2; i < defaultStreamChannelSize*4; i++ {
  1102  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1103  			t.Fatal(err)
  1104  		}
  1105  	}
  1106  
  1107  	err = loggerDriver.Close()
  1108  	if err != nil {
  1109  		t.Fatal(err)
  1110  	}
  1111  
  1112  	if len(hec.messages) != defaultStreamChannelSize*4 {
  1113  		t.Fatal("Not all messages delivered")
  1114  	}
  1115  
  1116  	for i, message := range hec.messages {
  1117  		if event, err := message.EventAsMap(); err != nil {
  1118  			t.Fatal(err)
  1119  		} else {
  1120  			if event["line"] != fmt.Sprintf("%d", i) {
  1121  				t.Fatalf("Unexpected event in message %v", event)
  1122  			}
  1123  		}
  1124  	}
  1125  
  1126  	err = hec.Close()
  1127  	if err != nil {
  1128  		t.Fatal(err)
  1129  	}
  1130  }
  1131  
  1132  // Verify logic for when we filled whole buffer
  1133  func TestBufferMaximum(t *testing.T) {
  1134  	if err := os.Setenv(envVarPostMessagesBatchSize, "2"); err != nil {
  1135  		t.Fatal(err)
  1136  	}
  1137  
  1138  	if err := os.Setenv(envVarBufferMaximum, "10"); err != nil {
  1139  		t.Fatal(err)
  1140  	}
  1141  
  1142  	if err := os.Setenv(envVarStreamChannelSize, "0"); err != nil {
  1143  		t.Fatal(err)
  1144  	}
  1145  
  1146  	hec := NewHTTPEventCollectorMock(t)
  1147  	hec.simulateErr(true)
  1148  	go hec.Serve()
  1149  
  1150  	info := logger.Info{
  1151  		Config: map[string]string{
  1152  			splunkURLKey:              hec.URL(),
  1153  			splunkTokenKey:            hec.token,
  1154  			splunkVerifyConnectionKey: "false",
  1155  		},
  1156  		ContainerID:        "containeriid",
  1157  		ContainerName:      "/container_name",
  1158  		ContainerImageID:   "contaimageid",
  1159  		ContainerImageName: "container_image_name",
  1160  	}
  1161  
  1162  	loggerDriver, err := New(info)
  1163  	if err != nil {
  1164  		t.Fatal(err)
  1165  	}
  1166  
  1167  	if hec.connectionVerified {
  1168  		t.Fatal("Connection should not be verified")
  1169  	}
  1170  
  1171  	for i := 0; i < 11; i++ {
  1172  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1173  			t.Fatal(err)
  1174  		}
  1175  	}
  1176  
  1177  	if len(hec.messages) != 0 {
  1178  		t.Fatal("No messages should be accepted at this point")
  1179  	}
  1180  
  1181  	hec.simulateServerError = false
  1182  
  1183  	err = loggerDriver.Close()
  1184  	if err != nil {
  1185  		t.Fatal(err)
  1186  	}
  1187  
  1188  	if len(hec.messages) != 9 {
  1189  		t.Fatalf("Expected # of messages %d, got %d", 9, len(hec.messages))
  1190  	}
  1191  
  1192  	// First 1000 messages are written to daemon log when buffer was full
  1193  	for i, message := range hec.messages {
  1194  		if event, err := message.EventAsMap(); err != nil {
  1195  			t.Fatal(err)
  1196  		} else {
  1197  			if event["line"] != fmt.Sprintf("%d", i+2) {
  1198  				t.Fatalf("Unexpected event in message %v", event)
  1199  			}
  1200  		}
  1201  	}
  1202  
  1203  	err = hec.Close()
  1204  	if err != nil {
  1205  		t.Fatal(err)
  1206  	}
  1207  
  1208  	if err := os.Setenv(envVarPostMessagesBatchSize, ""); err != nil {
  1209  		t.Fatal(err)
  1210  	}
  1211  
  1212  	if err := os.Setenv(envVarBufferMaximum, ""); err != nil {
  1213  		t.Fatal(err)
  1214  	}
  1215  
  1216  	if err := os.Setenv(envVarStreamChannelSize, ""); err != nil {
  1217  		t.Fatal(err)
  1218  	}
  1219  }
  1220  
  1221  // Verify that we are not blocking close when HEC is down for the whole time
  1222  func TestServerAlwaysDown(t *testing.T) {
  1223  	if err := os.Setenv(envVarPostMessagesBatchSize, "2"); err != nil {
  1224  		t.Fatal(err)
  1225  	}
  1226  
  1227  	if err := os.Setenv(envVarBufferMaximum, "4"); err != nil {
  1228  		t.Fatal(err)
  1229  	}
  1230  
  1231  	if err := os.Setenv(envVarStreamChannelSize, "0"); err != nil {
  1232  		t.Fatal(err)
  1233  	}
  1234  
  1235  	hec := NewHTTPEventCollectorMock(t)
  1236  	hec.simulateServerError = true
  1237  	go hec.Serve()
  1238  
  1239  	info := logger.Info{
  1240  		Config: map[string]string{
  1241  			splunkURLKey:              hec.URL(),
  1242  			splunkTokenKey:            hec.token,
  1243  			splunkVerifyConnectionKey: "false",
  1244  		},
  1245  		ContainerID:        "containeriid",
  1246  		ContainerName:      "/container_name",
  1247  		ContainerImageID:   "contaimageid",
  1248  		ContainerImageName: "container_image_name",
  1249  	}
  1250  
  1251  	loggerDriver, err := New(info)
  1252  	if err != nil {
  1253  		t.Fatal(err)
  1254  	}
  1255  
  1256  	if hec.connectionVerified {
  1257  		t.Fatal("Connection should not be verified")
  1258  	}
  1259  
  1260  	for i := 0; i < 5; i++ {
  1261  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1262  			t.Fatal(err)
  1263  		}
  1264  	}
  1265  
  1266  	err = loggerDriver.Close()
  1267  	if err != nil {
  1268  		t.Fatal(err)
  1269  	}
  1270  
  1271  	if len(hec.messages) != 0 {
  1272  		t.Fatal("No messages should be sent")
  1273  	}
  1274  
  1275  	err = hec.Close()
  1276  	if err != nil {
  1277  		t.Fatal(err)
  1278  	}
  1279  
  1280  	if err := os.Setenv(envVarPostMessagesBatchSize, ""); err != nil {
  1281  		t.Fatal(err)
  1282  	}
  1283  
  1284  	if err := os.Setenv(envVarBufferMaximum, ""); err != nil {
  1285  		t.Fatal(err)
  1286  	}
  1287  
  1288  	if err := os.Setenv(envVarStreamChannelSize, ""); err != nil {
  1289  		t.Fatal(err)
  1290  	}
  1291  }
  1292  
  1293  // Cannot send messages after we close driver
  1294  func TestCannotSendAfterClose(t *testing.T) {
  1295  	hec := NewHTTPEventCollectorMock(t)
  1296  	go hec.Serve()
  1297  
  1298  	info := logger.Info{
  1299  		Config: map[string]string{
  1300  			splunkURLKey:   hec.URL(),
  1301  			splunkTokenKey: hec.token,
  1302  		},
  1303  		ContainerID:        "containeriid",
  1304  		ContainerName:      "/container_name",
  1305  		ContainerImageID:   "contaimageid",
  1306  		ContainerImageName: "container_image_name",
  1307  	}
  1308  
  1309  	loggerDriver, err := New(info)
  1310  	if err != nil {
  1311  		t.Fatal(err)
  1312  	}
  1313  
  1314  	if err := loggerDriver.Log(&logger.Message{Line: []byte("message1"), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1315  		t.Fatal(err)
  1316  	}
  1317  
  1318  	err = loggerDriver.Close()
  1319  	if err != nil {
  1320  		t.Fatal(err)
  1321  	}
  1322  
  1323  	if err := loggerDriver.Log(&logger.Message{Line: []byte("message2"), Source: "stdout", Timestamp: time.Now()}); err == nil {
  1324  		t.Fatal("Driver should not allow to send messages after close")
  1325  	}
  1326  
  1327  	if len(hec.messages) != 1 {
  1328  		t.Fatal("Only one message should be sent")
  1329  	}
  1330  
  1331  	message := hec.messages[0]
  1332  	if event, err := message.EventAsMap(); err != nil {
  1333  		t.Fatal(err)
  1334  	} else {
  1335  		if event["line"] != "message1" {
  1336  			t.Fatalf("Unexpected event in message %v", event)
  1337  		}
  1338  	}
  1339  
  1340  	err = hec.Close()
  1341  	if err != nil {
  1342  		t.Fatal(err)
  1343  	}
  1344  }
  1345  
  1346  func TestDeadlockOnBlockedEndpoint(t *testing.T) {
  1347  	hec := NewHTTPEventCollectorMock(t)
  1348  	go hec.Serve()
  1349  	info := logger.Info{
  1350  		Config: map[string]string{
  1351  			splunkURLKey:   hec.URL(),
  1352  			splunkTokenKey: hec.token,
  1353  		},
  1354  		ContainerID:        "containeriid",
  1355  		ContainerName:      "/container_name",
  1356  		ContainerImageID:   "contaimageid",
  1357  		ContainerImageName: "container_image_name",
  1358  	}
  1359  
  1360  	l, err := New(info)
  1361  	if err != nil {
  1362  		t.Fatal(err)
  1363  	}
  1364  
  1365  	ctx, unblock := context.WithCancel(context.Background())
  1366  	hec.withBlock(ctx)
  1367  	defer unblock()
  1368  
  1369  	batchSendTimeout = 1 * time.Second
  1370  
  1371  	if err := l.Log(&logger.Message{}); err != nil {
  1372  		t.Fatal(err)
  1373  	}
  1374  
  1375  	done := make(chan struct{})
  1376  	go func() {
  1377  		l.Close()
  1378  		close(done)
  1379  	}()
  1380  
  1381  	select {
  1382  	case <-time.After(60 * time.Second):
  1383  		buf := make([]byte, 1e6)
  1384  		buf = buf[:runtime.Stack(buf, true)]
  1385  		t.Logf("STACK DUMP: \n\n%s\n\n", string(buf))
  1386  		t.Fatal("timeout waiting for close to finish")
  1387  	case <-done:
  1388  	}
  1389  }