gopkg.in/dotcloud/docker.v1@v1.13.1/daemon/logger/splunk/splunk_test.go (about)

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