| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | |
| 3 // that can be found in the LICENSE file. | |
| 4 | |
| 5 package cloudlogging | |
| 6 | |
| 7 import ( | |
| 8 "encoding/json" | |
| 9 "fmt" | |
| 10 "io/ioutil" | |
| 11 "net" | |
| 12 "net/http" | |
| 13 "net/http/httptest" | |
| 14 "net/url" | |
| 15 "strings" | |
| 16 "testing" | |
| 17 "time" | |
| 18 | |
| 19 . "github.com/smartystreets/goconvey/convey" | |
| 20 "google.golang.org/api/googleapi" | |
| 21 cloudlog "google.golang.org/api/logging/v1beta3" | |
| 22 ) | |
| 23 | |
| 24 type testLogRequest struct { | |
| 25 url *url.URL | |
| 26 contentType string | |
| 27 userAgent string | |
| 28 request cloudlog.WriteLogEntriesRequest | |
| 29 } | |
| 30 | |
| 31 type testCloudLoggingServer struct { | |
| 32 logC chan *testLogRequest | |
| 33 } | |
| 34 | |
| 35 func (h *testCloudLoggingServer) ServeHTTP(w http.ResponseWriter, req *http.Requ
est) { | |
| 36 defer req.Body.Close() | |
| 37 | |
| 38 body, err := ioutil.ReadAll(req.Body) | |
| 39 if err != nil { | |
| 40 http.Error(w, err.Error(), http.StatusInternalServerError) | |
| 41 return | |
| 42 } | |
| 43 | |
| 44 if req.Header.Get("content-type") != "application/json" { | |
| 45 http.Error(w, err.Error(), http.StatusBadRequest) | |
| 46 return | |
| 47 } | |
| 48 | |
| 49 testReq := testLogRequest{ | |
| 50 url: req.URL, | |
| 51 contentType: req.Header.Get("content-type"), | |
| 52 userAgent: req.Header.Get("user-agent"), | |
| 53 } | |
| 54 | |
| 55 if err := json.Unmarshal(body, &testReq.request); err != nil { | |
| 56 http.Error(w, err.Error(), http.StatusBadRequest) | |
| 57 return | |
| 58 } | |
| 59 | |
| 60 h.logC <- &testReq | |
| 61 | |
| 62 // Write an empty response to the client. | |
| 63 w.Write([]byte("{}")) | |
| 64 } | |
| 65 | |
| 66 func shouldResembleLogs(actual interface{}, expected ...interface{}) string { | |
| 67 errors := []string{} | |
| 68 addError := func(f string, args ...interface{}) { | |
| 69 errors = append(errors, fmt.Sprintf(f, args...)) | |
| 70 } | |
| 71 | |
| 72 actualEntries, ok := actual.([]*cloudlog.LogEntry) | |
| 73 if !ok { | |
| 74 return "Actual: Not a cloud log entry bundle." | |
| 75 } | |
| 76 | |
| 77 for i, act := range actualEntries { | |
| 78 if len(expected) == 0 { | |
| 79 addError("Actual #%d: additional entry %#v", i, act) | |
| 80 continue | |
| 81 } | |
| 82 | |
| 83 exp, ok := expected[i].(*cloudlog.LogEntry) | |
| 84 if !ok { | |
| 85 addError("Expected #%d: not a *cloudlog.LogEntry.", i) | |
| 86 continue | |
| 87 } | |
| 88 | |
| 89 actClone := *act | |
| 90 expClone := *exp | |
| 91 actClone.Metadata = nil | |
| 92 expClone.Metadata = nil | |
| 93 if err := ShouldResemble(actClone, expClone); err != "" { | |
| 94 addError("Entry #%d:\n Actual: %#v\n Expected: %#v\n
", i, &actClone, &expClone) | |
| 95 } | |
| 96 | |
| 97 if err := ShouldResemble(act.Metadata, exp.Metadata); err != ""
{ | |
| 98 addError("Entry #%d Metadata:\n Actual: %#v\n Expect
ed: %#v\n", | |
| 99 i, act.Metadata, exp.Metadata) | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 for i := len(actualEntries); i < len(expected); i++ { | |
| 104 addError("Expected #%d: additional entry %#v", i, expected[i]) | |
| 105 } | |
| 106 return strings.Join(errors, "\n") | |
| 107 } | |
| 108 | |
| 109 func TestClient(t *testing.T) { | |
| 110 t.Parallel() | |
| 111 now := time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC) | |
| 112 | |
| 113 Convey(`A client connected to a testing server`, t, func() { | |
| 114 opts := ClientOptions{ | |
| 115 UserAgent: "client.go test client", | |
| 116 ProjectID: "test-project", | |
| 117 LogID: "test-log-id", | |
| 118 ResourceType: "test-resource", | |
| 119 ResourceID: "test-resource-id", | |
| 120 } | |
| 121 | |
| 122 h := &testCloudLoggingServer{ | |
| 123 logC: make(chan *testLogRequest, 1), | |
| 124 } | |
| 125 srv := httptest.NewServer(h) | |
| 126 defer srv.Close() | |
| 127 | |
| 128 tr := &http.Transport{ | |
| 129 DialTLS: func(network, addr string) (net.Conn, error) { | |
| 130 u, err := url.Parse(srv.URL) | |
| 131 if err != nil { | |
| 132 return nil, err | |
| 133 } | |
| 134 return net.Dial(network, u.Host) | |
| 135 }, | |
| 136 } | |
| 137 client := &http.Client{ | |
| 138 Transport: tr, | |
| 139 } | |
| 140 | |
| 141 c, err := NewClient(opts, client) | |
| 142 So(err, ShouldBeNil) | |
| 143 | |
| 144 Convey(`Can send a log entry bundle.`, func() { | |
| 145 err = c.PushEntries([]*Entry{ | |
| 146 { | |
| 147 InsertID: "test-log-0", | |
| 148 Timestamp: now, | |
| 149 Severity: Debug, | |
| 150 TextPayload: "hi", | |
| 151 Labels: Labels{ | |
| 152 "foo": "bar", | |
| 153 }, | |
| 154 }, | |
| 155 { | |
| 156 InsertID: "test-log-1", | |
| 157 Timestamp: now, | |
| 158 Severity: Info, | |
| 159 TextPayload: "sup", | |
| 160 Labels: Labels{ | |
| 161 "baz": "qux", | |
| 162 }, | |
| 163 }, | |
| 164 }) | |
| 165 So(err, ShouldBeNil) | |
| 166 | |
| 167 req := <-h.logC | |
| 168 So(req.url.Path, ShouldEqual, "/v1beta3/projects/test-pr
oject/logs/test-log-id/entries:write") | |
| 169 So(req.contentType, ShouldEqual, "application/json") | |
| 170 So(req.userAgent, ShouldEqual, googleapi.UserAgent+" cli
ent.go test client") | |
| 171 So(req.request.CommonLabels, ShouldResemble, map[string]
string{ | |
| 172 "compute.googleapis.com/resource_type": "test-re
source", | |
| 173 "compute.googleapis.com/resource_id": "test-re
source-id", | |
| 174 }) | |
| 175 So(req.request.Entries, shouldResembleLogs, | |
| 176 &cloudlog.LogEntry{ | |
| 177 InsertId: "test-log-0", | |
| 178 Metadata: &cloudlog.LogEntryMetadata{ | |
| 179 Labels: map[string]string{ | |
| 180 "foo": "bar", | |
| 181 }, | |
| 182 ProjectId: "test-project", | |
| 183 Severity: "DEBUG", | |
| 184 Timestamp: "2015-01-01T00:00:00Z
", | |
| 185 }, | |
| 186 TextPayload: "hi", | |
| 187 }, | |
| 188 | |
| 189 &cloudlog.LogEntry{ | |
| 190 InsertId: "test-log-1", | |
| 191 Metadata: &cloudlog.LogEntryMetadata{ | |
| 192 Labels: map[string]string{ | |
| 193 "baz": "qux", | |
| 194 }, | |
| 195 ProjectId: "test-project", | |
| 196 Severity: "INFO", | |
| 197 Timestamp: "2015-01-01T00:00:00Z
", | |
| 198 }, | |
| 199 TextPayload: "sup", | |
| 200 }, | |
| 201 ) | |
| 202 }) | |
| 203 }) | |
| 204 } | |
| OLD | NEW |