github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+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  	"os"
     9  	"runtime"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/docker/docker/daemon/logger"
    14  	"gotest.tools/v3/assert"
    15  	"gotest.tools/v3/env"
    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  	assert.NilError(t, err)
   103  	splunkLogger := logger.(*splunkLoggerInline)
   104  
   105  	proxyFunc := splunkLogger.transport.Proxy
   106  	assert.Assert(t, proxyFunc != nil)
   107  
   108  	req, err := http.NewRequest(http.MethodGet, splunkURL, nil)
   109  	assert.NilError(t, err)
   110  
   111  	proxyURL, err := proxyFunc(req)
   112  	assert.NilError(t, err)
   113  	assert.Assert(t, proxyURL != nil)
   114  	assert.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  	assert.NilError(t, err)
   487  
   488  	loggerDriver, err := New(info)
   489  	assert.NilError(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  	expectedRequests := 9
   929  	if runtime.GOOS == "windows" {
   930  		// sometimes in Windows, this test fails with number of requests showing 8. So be more conservative.
   931  		expectedRequests = 7
   932  	}
   933  	if hec.numOfRequests < expectedRequests {
   934  		t.Fatalf("Unexpected number of requests %d", hec.numOfRequests)
   935  	}
   936  
   937  	err = hec.Close()
   938  	if err != nil {
   939  		t.Fatal(err)
   940  	}
   941  
   942  	if err := os.Setenv(envVarPostMessagesFrequency, ""); err != nil {
   943  		t.Fatal(err)
   944  	}
   945  }
   946  
   947  // Simulate behavior similar to first version of Splunk Logging Driver, when we were sending one message
   948  // per request
   949  func TestOneMessagePerRequest(t *testing.T) {
   950  	if err := os.Setenv(envVarPostMessagesFrequency, "10h"); err != nil {
   951  		t.Fatal(err)
   952  	}
   953  
   954  	if err := os.Setenv(envVarPostMessagesBatchSize, "1"); err != nil {
   955  		t.Fatal(err)
   956  	}
   957  
   958  	if err := os.Setenv(envVarBufferMaximum, "1"); err != nil {
   959  		t.Fatal(err)
   960  	}
   961  
   962  	if err := os.Setenv(envVarStreamChannelSize, "0"); err != nil {
   963  		t.Fatal(err)
   964  	}
   965  
   966  	hec := NewHTTPEventCollectorMock(t)
   967  
   968  	go hec.Serve()
   969  
   970  	info := logger.Info{
   971  		Config: map[string]string{
   972  			splunkURLKey:   hec.URL(),
   973  			splunkTokenKey: hec.token,
   974  		},
   975  		ContainerID:        "containeriid",
   976  		ContainerName:      "/container_name",
   977  		ContainerImageID:   "contaimageid",
   978  		ContainerImageName: "container_image_name",
   979  	}
   980  
   981  	loggerDriver, err := New(info)
   982  	if err != nil {
   983  		t.Fatal(err)
   984  	}
   985  
   986  	for i := 0; i < 10; i++ {
   987  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
   988  			t.Fatal(err)
   989  		}
   990  	}
   991  
   992  	err = loggerDriver.Close()
   993  	if err != nil {
   994  		t.Fatal(err)
   995  	}
   996  
   997  	if len(hec.messages) != 10 {
   998  		t.Fatal("Not all messages delivered")
   999  	}
  1000  
  1001  	for i, message := range hec.messages {
  1002  		if event, err := message.EventAsMap(); err != nil {
  1003  			t.Fatal(err)
  1004  		} else {
  1005  			if event["line"] != fmt.Sprintf("%d", i) {
  1006  				t.Fatalf("Unexpected event in message %v", event)
  1007  			}
  1008  		}
  1009  	}
  1010  
  1011  	// 1 to verify connection and 10 messages
  1012  	if hec.numOfRequests != 11 {
  1013  		t.Fatalf("Unexpected number of requests %d", hec.numOfRequests)
  1014  	}
  1015  
  1016  	err = hec.Close()
  1017  	if err != nil {
  1018  		t.Fatal(err)
  1019  	}
  1020  
  1021  	if err := os.Setenv(envVarPostMessagesFrequency, ""); err != nil {
  1022  		t.Fatal(err)
  1023  	}
  1024  
  1025  	if err := os.Setenv(envVarPostMessagesBatchSize, ""); err != nil {
  1026  		t.Fatal(err)
  1027  	}
  1028  
  1029  	if err := os.Setenv(envVarBufferMaximum, ""); err != nil {
  1030  		t.Fatal(err)
  1031  	}
  1032  
  1033  	if err := os.Setenv(envVarStreamChannelSize, ""); err != nil {
  1034  		t.Fatal(err)
  1035  	}
  1036  }
  1037  
  1038  // Driver should not be created when HEC is unresponsive
  1039  func TestVerify(t *testing.T) {
  1040  	hec := NewHTTPEventCollectorMock(t)
  1041  	hec.simulateServerError = true
  1042  	go hec.Serve()
  1043  
  1044  	info := logger.Info{
  1045  		Config: map[string]string{
  1046  			splunkURLKey:   hec.URL(),
  1047  			splunkTokenKey: hec.token,
  1048  		},
  1049  		ContainerID:        "containeriid",
  1050  		ContainerName:      "/container_name",
  1051  		ContainerImageID:   "contaimageid",
  1052  		ContainerImageName: "container_image_name",
  1053  	}
  1054  
  1055  	_, err := New(info)
  1056  	if err == nil {
  1057  		t.Fatal("Expecting driver to fail, when server is unresponsive")
  1058  	}
  1059  
  1060  	err = hec.Close()
  1061  	if err != nil {
  1062  		t.Fatal(err)
  1063  	}
  1064  }
  1065  
  1066  // Verify that user can specify to skip verification that Splunk HEC is working.
  1067  // Also in this test we verify retry logic.
  1068  func TestSkipVerify(t *testing.T) {
  1069  	hec := NewHTTPEventCollectorMock(t)
  1070  	hec.simulateServerError = true
  1071  	go hec.Serve()
  1072  
  1073  	info := logger.Info{
  1074  		Config: map[string]string{
  1075  			splunkURLKey:              hec.URL(),
  1076  			splunkTokenKey:            hec.token,
  1077  			splunkVerifyConnectionKey: "false",
  1078  		},
  1079  		ContainerID:        "containeriid",
  1080  		ContainerName:      "/container_name",
  1081  		ContainerImageID:   "contaimageid",
  1082  		ContainerImageName: "container_image_name",
  1083  	}
  1084  
  1085  	loggerDriver, err := New(info)
  1086  	if err != nil {
  1087  		t.Fatal(err)
  1088  	}
  1089  
  1090  	if hec.connectionVerified {
  1091  		t.Fatal("Connection should not be verified")
  1092  	}
  1093  
  1094  	for i := 0; i < defaultStreamChannelSize*2; i++ {
  1095  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1096  			t.Fatal(err)
  1097  		}
  1098  	}
  1099  
  1100  	if len(hec.messages) != 0 {
  1101  		t.Fatal("No messages should be accepted at this point")
  1102  	}
  1103  
  1104  	hec.simulateErr(false)
  1105  
  1106  	for i := defaultStreamChannelSize * 2; i < defaultStreamChannelSize*4; i++ {
  1107  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1108  			t.Fatal(err)
  1109  		}
  1110  	}
  1111  
  1112  	err = loggerDriver.Close()
  1113  	if err != nil {
  1114  		t.Fatal(err)
  1115  	}
  1116  
  1117  	if len(hec.messages) != defaultStreamChannelSize*4 {
  1118  		t.Fatal("Not all messages delivered")
  1119  	}
  1120  
  1121  	for i, message := range hec.messages {
  1122  		if event, err := message.EventAsMap(); err != nil {
  1123  			t.Fatal(err)
  1124  		} else {
  1125  			if event["line"] != fmt.Sprintf("%d", i) {
  1126  				t.Fatalf("Unexpected event in message %v", event)
  1127  			}
  1128  		}
  1129  	}
  1130  
  1131  	err = hec.Close()
  1132  	if err != nil {
  1133  		t.Fatal(err)
  1134  	}
  1135  }
  1136  
  1137  // Verify logic for when we filled whole buffer
  1138  func TestBufferMaximum(t *testing.T) {
  1139  	if err := os.Setenv(envVarPostMessagesBatchSize, "2"); err != nil {
  1140  		t.Fatal(err)
  1141  	}
  1142  
  1143  	if err := os.Setenv(envVarBufferMaximum, "10"); err != nil {
  1144  		t.Fatal(err)
  1145  	}
  1146  
  1147  	if err := os.Setenv(envVarStreamChannelSize, "0"); err != nil {
  1148  		t.Fatal(err)
  1149  	}
  1150  
  1151  	hec := NewHTTPEventCollectorMock(t)
  1152  	hec.simulateErr(true)
  1153  	go hec.Serve()
  1154  
  1155  	info := logger.Info{
  1156  		Config: map[string]string{
  1157  			splunkURLKey:              hec.URL(),
  1158  			splunkTokenKey:            hec.token,
  1159  			splunkVerifyConnectionKey: "false",
  1160  		},
  1161  		ContainerID:        "containeriid",
  1162  		ContainerName:      "/container_name",
  1163  		ContainerImageID:   "contaimageid",
  1164  		ContainerImageName: "container_image_name",
  1165  	}
  1166  
  1167  	loggerDriver, err := New(info)
  1168  	if err != nil {
  1169  		t.Fatal(err)
  1170  	}
  1171  
  1172  	if hec.connectionVerified {
  1173  		t.Fatal("Connection should not be verified")
  1174  	}
  1175  
  1176  	for i := 0; i < 11; i++ {
  1177  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1178  			t.Fatal(err)
  1179  		}
  1180  	}
  1181  
  1182  	if len(hec.messages) != 0 {
  1183  		t.Fatal("No messages should be accepted at this point")
  1184  	}
  1185  
  1186  	hec.simulateServerError = false
  1187  
  1188  	err = loggerDriver.Close()
  1189  	if err != nil {
  1190  		t.Fatal(err)
  1191  	}
  1192  
  1193  	if len(hec.messages) != 9 {
  1194  		t.Fatalf("Expected # of messages %d, got %d", 9, len(hec.messages))
  1195  	}
  1196  
  1197  	// First 1000 messages are written to daemon log when buffer was full
  1198  	for i, message := range hec.messages {
  1199  		if event, err := message.EventAsMap(); err != nil {
  1200  			t.Fatal(err)
  1201  		} else {
  1202  			if event["line"] != fmt.Sprintf("%d", i+2) {
  1203  				t.Fatalf("Unexpected event in message %v", event)
  1204  			}
  1205  		}
  1206  	}
  1207  
  1208  	err = hec.Close()
  1209  	if err != nil {
  1210  		t.Fatal(err)
  1211  	}
  1212  
  1213  	if err := os.Setenv(envVarPostMessagesBatchSize, ""); err != nil {
  1214  		t.Fatal(err)
  1215  	}
  1216  
  1217  	if err := os.Setenv(envVarBufferMaximum, ""); err != nil {
  1218  		t.Fatal(err)
  1219  	}
  1220  
  1221  	if err := os.Setenv(envVarStreamChannelSize, ""); err != nil {
  1222  		t.Fatal(err)
  1223  	}
  1224  }
  1225  
  1226  // Verify that we are not blocking close when HEC is down for the whole time
  1227  func TestServerAlwaysDown(t *testing.T) {
  1228  	if err := os.Setenv(envVarPostMessagesBatchSize, "2"); err != nil {
  1229  		t.Fatal(err)
  1230  	}
  1231  
  1232  	if err := os.Setenv(envVarBufferMaximum, "4"); err != nil {
  1233  		t.Fatal(err)
  1234  	}
  1235  
  1236  	if err := os.Setenv(envVarStreamChannelSize, "0"); err != nil {
  1237  		t.Fatal(err)
  1238  	}
  1239  
  1240  	hec := NewHTTPEventCollectorMock(t)
  1241  	hec.simulateServerError = true
  1242  	go hec.Serve()
  1243  
  1244  	info := logger.Info{
  1245  		Config: map[string]string{
  1246  			splunkURLKey:              hec.URL(),
  1247  			splunkTokenKey:            hec.token,
  1248  			splunkVerifyConnectionKey: "false",
  1249  		},
  1250  		ContainerID:        "containeriid",
  1251  		ContainerName:      "/container_name",
  1252  		ContainerImageID:   "contaimageid",
  1253  		ContainerImageName: "container_image_name",
  1254  	}
  1255  
  1256  	loggerDriver, err := New(info)
  1257  	if err != nil {
  1258  		t.Fatal(err)
  1259  	}
  1260  
  1261  	if hec.connectionVerified {
  1262  		t.Fatal("Connection should not be verified")
  1263  	}
  1264  
  1265  	for i := 0; i < 5; i++ {
  1266  		if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1267  			t.Fatal(err)
  1268  		}
  1269  	}
  1270  
  1271  	err = loggerDriver.Close()
  1272  	if err != nil {
  1273  		t.Fatal(err)
  1274  	}
  1275  
  1276  	if len(hec.messages) != 0 {
  1277  		t.Fatal("No messages should be sent")
  1278  	}
  1279  
  1280  	err = hec.Close()
  1281  	if err != nil {
  1282  		t.Fatal(err)
  1283  	}
  1284  
  1285  	if err := os.Setenv(envVarPostMessagesBatchSize, ""); err != nil {
  1286  		t.Fatal(err)
  1287  	}
  1288  
  1289  	if err := os.Setenv(envVarBufferMaximum, ""); err != nil {
  1290  		t.Fatal(err)
  1291  	}
  1292  
  1293  	if err := os.Setenv(envVarStreamChannelSize, ""); err != nil {
  1294  		t.Fatal(err)
  1295  	}
  1296  }
  1297  
  1298  // Cannot send messages after we close driver
  1299  func TestCannotSendAfterClose(t *testing.T) {
  1300  	hec := NewHTTPEventCollectorMock(t)
  1301  	go hec.Serve()
  1302  
  1303  	info := logger.Info{
  1304  		Config: map[string]string{
  1305  			splunkURLKey:   hec.URL(),
  1306  			splunkTokenKey: hec.token,
  1307  		},
  1308  		ContainerID:        "containeriid",
  1309  		ContainerName:      "/container_name",
  1310  		ContainerImageID:   "contaimageid",
  1311  		ContainerImageName: "container_image_name",
  1312  	}
  1313  
  1314  	loggerDriver, err := New(info)
  1315  	if err != nil {
  1316  		t.Fatal(err)
  1317  	}
  1318  
  1319  	if err := loggerDriver.Log(&logger.Message{Line: []byte("message1"), Source: "stdout", Timestamp: time.Now()}); err != nil {
  1320  		t.Fatal(err)
  1321  	}
  1322  
  1323  	err = loggerDriver.Close()
  1324  	if err != nil {
  1325  		t.Fatal(err)
  1326  	}
  1327  
  1328  	if err := loggerDriver.Log(&logger.Message{Line: []byte("message2"), Source: "stdout", Timestamp: time.Now()}); err == nil {
  1329  		t.Fatal("Driver should not allow to send messages after close")
  1330  	}
  1331  
  1332  	if len(hec.messages) != 1 {
  1333  		t.Fatal("Only one message should be sent")
  1334  	}
  1335  
  1336  	message := hec.messages[0]
  1337  	if event, err := message.EventAsMap(); err != nil {
  1338  		t.Fatal(err)
  1339  	} else {
  1340  		if event["line"] != "message1" {
  1341  			t.Fatalf("Unexpected event in message %v", event)
  1342  		}
  1343  	}
  1344  
  1345  	err = hec.Close()
  1346  	if err != nil {
  1347  		t.Fatal(err)
  1348  	}
  1349  }
  1350  
  1351  func TestDeadlockOnBlockedEndpoint(t *testing.T) {
  1352  	hec := NewHTTPEventCollectorMock(t)
  1353  	go hec.Serve()
  1354  	info := logger.Info{
  1355  		Config: map[string]string{
  1356  			splunkURLKey:   hec.URL(),
  1357  			splunkTokenKey: hec.token,
  1358  		},
  1359  		ContainerID:        "containeriid",
  1360  		ContainerName:      "/container_name",
  1361  		ContainerImageID:   "contaimageid",
  1362  		ContainerImageName: "container_image_name",
  1363  	}
  1364  
  1365  	l, err := New(info)
  1366  	if err != nil {
  1367  		t.Fatal(err)
  1368  	}
  1369  
  1370  	ctx, unblock := context.WithCancel(context.Background())
  1371  	hec.withBlock(ctx)
  1372  	defer unblock()
  1373  
  1374  	batchSendTimeout = 1 * time.Second
  1375  
  1376  	if err := l.Log(&logger.Message{}); err != nil {
  1377  		t.Fatal(err)
  1378  	}
  1379  
  1380  	done := make(chan struct{})
  1381  	go func() {
  1382  		l.Close()
  1383  		close(done)
  1384  	}()
  1385  
  1386  	select {
  1387  	case <-time.After(60 * time.Second):
  1388  		buf := make([]byte, 1e6)
  1389  		buf = buf[:runtime.Stack(buf, true)]
  1390  		t.Logf("STACK DUMP: \n\n%s\n\n", string(buf))
  1391  		t.Fatal("timeout waiting for close to finish")
  1392  	case <-done:
  1393  	}
  1394  }