github.com/hms58/moby@v1.13.1/daemon/logger/splunk/splunkhecmock_test.go (about)

     1  package splunk
     2  
     3  import (
     4  	"compress/gzip"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"net"
    10  	"net/http"
    11  	"testing"
    12  )
    13  
    14  func (message *splunkMessage) EventAsString() (string, error) {
    15  	if val, ok := message.Event.(string); ok {
    16  		return val, nil
    17  	}
    18  	return "", fmt.Errorf("Cannot cast Event %v to string", message.Event)
    19  }
    20  
    21  func (message *splunkMessage) EventAsMap() (map[string]interface{}, error) {
    22  	if val, ok := message.Event.(map[string]interface{}); ok {
    23  		return val, nil
    24  	}
    25  	return nil, fmt.Errorf("Cannot cast Event %v to map", message.Event)
    26  }
    27  
    28  type HTTPEventCollectorMock struct {
    29  	tcpAddr     *net.TCPAddr
    30  	tcpListener *net.TCPListener
    31  
    32  	token               string
    33  	simulateServerError bool
    34  
    35  	test *testing.T
    36  
    37  	connectionVerified bool
    38  	gzipEnabled        *bool
    39  	messages           []*splunkMessage
    40  	numOfRequests      int
    41  }
    42  
    43  func NewHTTPEventCollectorMock(t *testing.T) *HTTPEventCollectorMock {
    44  	tcpAddr := &net.TCPAddr{IP: []byte{127, 0, 0, 1}, Port: 0, Zone: ""}
    45  	tcpListener, err := net.ListenTCP("tcp", tcpAddr)
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	return &HTTPEventCollectorMock{
    50  		tcpAddr:             tcpAddr,
    51  		tcpListener:         tcpListener,
    52  		token:               "4642492F-D8BD-47F1-A005-0C08AE4657DF",
    53  		simulateServerError: false,
    54  		test:                t,
    55  		connectionVerified:  false}
    56  }
    57  
    58  func (hec *HTTPEventCollectorMock) URL() string {
    59  	return "http://" + hec.tcpListener.Addr().String()
    60  }
    61  
    62  func (hec *HTTPEventCollectorMock) Serve() error {
    63  	return http.Serve(hec.tcpListener, hec)
    64  }
    65  
    66  func (hec *HTTPEventCollectorMock) Close() error {
    67  	return hec.tcpListener.Close()
    68  }
    69  
    70  func (hec *HTTPEventCollectorMock) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
    71  	var err error
    72  
    73  	hec.numOfRequests++
    74  
    75  	if hec.simulateServerError {
    76  		if request.Body != nil {
    77  			defer request.Body.Close()
    78  		}
    79  		writer.WriteHeader(http.StatusInternalServerError)
    80  		return
    81  	}
    82  
    83  	switch request.Method {
    84  	case http.MethodOptions:
    85  		// Verify that options method is getting called only once
    86  		if hec.connectionVerified {
    87  			hec.test.Errorf("Connection should not be verified more than once. Got second request with %s method.", request.Method)
    88  		}
    89  		hec.connectionVerified = true
    90  		writer.WriteHeader(http.StatusOK)
    91  	case http.MethodPost:
    92  		// Always verify that Driver is using correct path to HEC
    93  		if request.URL.String() != "/services/collector/event/1.0" {
    94  			hec.test.Errorf("Unexpected path %v", request.URL)
    95  		}
    96  		defer request.Body.Close()
    97  
    98  		if authorization, ok := request.Header["Authorization"]; !ok || authorization[0] != ("Splunk "+hec.token) {
    99  			hec.test.Error("Authorization header is invalid.")
   100  		}
   101  
   102  		gzipEnabled := false
   103  		if contentEncoding, ok := request.Header["Content-Encoding"]; ok && contentEncoding[0] == "gzip" {
   104  			gzipEnabled = true
   105  		}
   106  
   107  		if hec.gzipEnabled == nil {
   108  			hec.gzipEnabled = &gzipEnabled
   109  		} else if gzipEnabled != *hec.gzipEnabled {
   110  			// Nothing wrong with that, but we just know that Splunk Logging Driver does not do that
   111  			hec.test.Error("Driver should not change Content Encoding.")
   112  		}
   113  
   114  		var gzipReader *gzip.Reader
   115  		var reader io.Reader
   116  		if gzipEnabled {
   117  			gzipReader, err = gzip.NewReader(request.Body)
   118  			if err != nil {
   119  				hec.test.Fatal(err)
   120  			}
   121  			reader = gzipReader
   122  		} else {
   123  			reader = request.Body
   124  		}
   125  
   126  		// Read body
   127  		var body []byte
   128  		body, err = ioutil.ReadAll(reader)
   129  		if err != nil {
   130  			hec.test.Fatal(err)
   131  		}
   132  
   133  		// Parse message
   134  		messageStart := 0
   135  		for i := 0; i < len(body); i++ {
   136  			if i == len(body)-1 || (body[i] == '}' && body[i+1] == '{') {
   137  				var message splunkMessage
   138  				err = json.Unmarshal(body[messageStart:i+1], &message)
   139  				if err != nil {
   140  					hec.test.Log(string(body[messageStart : i+1]))
   141  					hec.test.Fatal(err)
   142  				}
   143  				hec.messages = append(hec.messages, &message)
   144  				messageStart = i + 1
   145  			}
   146  		}
   147  
   148  		if gzipEnabled {
   149  			gzipReader.Close()
   150  		}
   151  
   152  		writer.WriteHeader(http.StatusOK)
   153  	default:
   154  		hec.test.Errorf("Unexpected HTTP method %s", http.MethodOptions)
   155  		writer.WriteHeader(http.StatusBadRequest)
   156  	}
   157  }