github.com/rumpl/bof@v23.0.0-rc.2+incompatible/daemon/logger/splunk/splunk_test.go (about)

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