github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/daemon/logger/splunk/splunk_test.go (about)

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