@@ -18,7 +18,6 @@ import (
1818 "context"
1919 "fmt"
2020 "strings"
21- "testing"
2221
2322 monitoring "cloud.google.com/go/monitoring/apiv3"
2423 gax "github.com/googleapis/gax-go"
5049)
5150
5251func init () {
53- // For testing convenience, we reduce maximum time series that metric client accepts.
54- MaxTimeSeriesPerUpload = 3
55-
5652 // Mock functions.
5753 newMetricClient = mockNewMetricClient
5854 createTimeSeries = mockCreateTimeSeries
@@ -126,22 +122,29 @@ func mockAddToBundler(bndler *bundler.Bundler, item interface{}, _ int) error {
126122// One of these functions once and only once, and never call NewExporter() directly.
127123
128124// newTestExp creates an exporter which saves error to errStorage. Caller should not set
129- // opts.OnError.
130- func newTestExp (t * testing. T , opts Options ) * Exporter {
125+ // opts.OnError and opts.BundleCountThreshold .
126+ func newTestExp (opts Options ) ( * Exporter , error ) {
131127 opts .OnError = testOnError
128+ // For testing convenience, we reduce the number of timeseris in one upload monitoring API
129+ // call.
130+ opts .BundleCountThreshold = 3
132131 exp , err := NewExporter (ctx , opts )
133132 if err != nil {
134- t . Fatalf ("creating exporter failed: %v" , err )
133+ return nil , fmt . Errorf ("creating exporter failed: %v" , err )
135134 }
136135 // Expose projDataMap so that mockAddToBundler() can use it.
137136 projDataMap = exp .projDataMap
138- return exp
137+ return exp , nil
139138}
140139
141140// newTestProjData creates a projectData object to test behavior of projectData.uploadRowData. Other
142141// uses are not recommended. As newTestExp, all errors are saved to errStorage.
143- func newTestProjData (t * testing.T , opts Options ) * projectData {
144- return newTestExp (t , opts ).newProjectData (project1 )
142+ func newTestProjData (opts Options ) (* projectData , error ) {
143+ exp , err := newTestExp (opts )
144+ if err != nil {
145+ return nil , err
146+ }
147+ return exp .newProjectData (project1 ), nil
145148}
146149
147150// We define a storage for all errors happened in export operation.
@@ -157,33 +160,54 @@ func testOnError(err error, rds ...*RowData) {
157160 errStorage = append (errStorage , errRowData {err , rds })
158161}
159162
163+ // multiError stores a sequence of errors. To convert it to an actual error, call toError().
164+ type multiError struct {
165+ errs []error
166+ }
167+
168+ func (me * multiError ) addf (format string , args ... interface {}) {
169+ me .errs = append (me .errs , fmt .Errorf (format , args ... ))
170+ }
171+
172+ func (me * multiError ) toError () error {
173+ switch len (me .errs ) {
174+ case 0 :
175+ return nil
176+ case 1 :
177+ return me .errs [0 ]
178+ default :
179+ return fmt .Errorf ("multiple errors: %q" , me .errs )
180+ }
181+ }
182+
160183// checkMetricClient checks all recorded requests to the metric client. We only compare int64
161184// values of the time series. To make this work, we assigned different int64 values for all valid
162185// rows in the test.
163- func checkMetricClient (t * testing. T , wantReqsValues [][]int64 ) {
186+ func checkMetricClient (wantReqsValues [][]int64 ) error {
164187 reqsLen , wantReqsLen := len (timeSeriesReqs ), len (wantReqsValues )
165188 if reqsLen != wantReqsLen {
166- t .Errorf ("number of requests got: %d, want %d" , reqsLen , wantReqsLen )
167- return
189+ return fmt .Errorf ("number of requests got: %d, want %d" , reqsLen , wantReqsLen )
168190 }
191+ var errs multiError
169192 for i := 0 ; i < reqsLen ; i ++ {
170193 prefix := fmt .Sprintf ("%d-th request mismatch" , i + 1 )
171194 tsArr := timeSeriesReqs [i ].TimeSeries
172195 wantTsValues := wantReqsValues [i ]
173196 tsArrLen , wantTsArrLen := len (tsArr ), len (wantTsValues )
174197 if tsArrLen != wantTsArrLen {
175- t . Errorf ("%s: number of time series got: %d, want: %d" , prefix , tsArrLen , wantTsArrLen )
198+ errs . addf ("%s: number of time series got: %d, want: %d" , prefix , tsArrLen , wantTsArrLen )
176199 continue
177200 }
178201 for j := 0 ; j < tsArrLen ; j ++ {
179202 // This is how monitoring API stores the int64 value.
180203 tsVal := tsArr [j ].Points [0 ].Value .Value .(* mpb.TypedValue_Int64Value ).Int64Value
181204 wantTsVal := wantTsValues [j ]
182205 if tsVal != wantTsVal {
183- t . Errorf ("%s: Value got: %d, want: %d" , prefix , tsVal , wantTsVal )
206+ errs . addf ("%s: Value got: %d, want: %d" , prefix , tsVal , wantTsVal )
184207 }
185208 }
186209 }
210+ return errs .toError ()
187211}
188212
189213// errRowDataCheck contains data for checking content of error storage.
@@ -193,96 +217,99 @@ type errRowDataCheck struct {
193217}
194218
195219// checkErrStorage checks content of error storage. For returned errors, we check prefix and suffix.
196- func checkErrStorage (t * testing. T , wantErrRdCheck []errRowDataCheck ) {
220+ func checkErrStorage (wantErrRdCheck []errRowDataCheck ) error {
197221 gotLen , wantLen := len (errStorage ), len (wantErrRdCheck )
198222 if gotLen != wantLen {
199- t .Errorf ("number of reported errors: %d, want: %d" , gotLen , wantLen )
200- return
223+ return fmt .Errorf ("number of reported errors: %d, want: %d" , gotLen , wantLen )
201224 }
225+ var errs multiError
202226 for i := 0 ; i < gotLen ; i ++ {
203227 prefix := fmt .Sprintf ("%d-th reported error mismatch" , i + 1 )
204228 errRd , wantErrRd := errStorage [i ], wantErrRdCheck [i ]
205229 errStr := errRd .err .Error ()
206230 if errPrefix := wantErrRd .errPrefix ; ! strings .HasPrefix (errStr , errPrefix ) {
207- t . Errorf ("%s: error got: %q, want: prefixed by %q" , prefix , errStr , errPrefix )
231+ errs . addf ("%s: error got: %q, want: prefixed by %q" , prefix , errStr , errPrefix )
208232 }
209233 if errSuffix := wantErrRd .errSuffix ; ! strings .HasSuffix (errStr , errSuffix ) {
210- t . Errorf ("%s: error got: %q, want: suffiexd by %q" , prefix , errStr , errSuffix )
234+ errs . addf ("%s: error got: %q, want: suffiexd by %q" , prefix , errStr , errSuffix )
211235 }
212236 if err := checkRowDataArr (errRd .rds , wantErrRd .rds ); err != nil {
213- t . Errorf ("%s: RowData array mismatch: %v" , prefix , err )
237+ errs . addf ("%s: RowData array mismatch: %v" , prefix , err )
214238 }
215239 }
240+ return errs .toError ()
216241}
217242
218243func checkRowDataArr (rds , wantRds []* RowData ) error {
219244 rdLen , wantRdLen := len (rds ), len (wantRds )
220245 if rdLen != wantRdLen {
221246 return fmt .Errorf ("number row data got: %d, want: %d" , rdLen , wantRdLen )
222247 }
248+ var errs multiError
223249 for i := 0 ; i < rdLen ; i ++ {
224250 if err := checkRowData (rds [i ], wantRds [i ]); err != nil {
225- return fmt . Errorf ("%d-th row data mismatch: %v" , i + 1 , err )
251+ errs . addf ("%d-th row data mismatch: %v" , i + 1 , err )
226252 }
227253 }
228- return nil
254+ return errs . toError ()
229255}
230256
231257func checkRowData (rd , wantRd * RowData ) error {
258+ var errs multiError
232259 if rd .View != wantRd .View {
233- return fmt . Errorf ("View got: %s, want: %s" , rd .View .Name , wantRd .View .Name )
260+ errs . addf ("View got: %s, want: %s" , rd .View .Name , wantRd .View .Name )
234261 }
235262 if rd .Start != wantRd .Start {
236- return fmt . Errorf ("Start got: %v, want: %v" , rd .Start , wantRd .Start )
263+ errs . addf ("Start got: %v, want: %v" , rd .Start , wantRd .Start )
237264 }
238265 if rd .End != wantRd .End {
239- return fmt . Errorf ("End got: %v, want: %v" , rd .End , wantRd .End )
266+ errs . addf ("End got: %v, want: %v" , rd .End , wantRd .End )
240267 }
241268 if rd .Row != wantRd .Row {
242- return fmt . Errorf ("Row got: %v, want: %v" , rd .Row , wantRd .Row )
269+ errs . addf ("Row got: %v, want: %v" , rd .Row , wantRd .Row )
243270 }
244- return nil
271+ return errs . toError ()
245272}
246273
247274// checkProjData checks all data passed to the bundler by bundler.Add().
248- func checkProjData (t * testing.T , wantProjData map [string ][]* RowData ) {
249- wantProj := map [string ]bool {}
250- for proj := range wantProjData {
251- wantProj [proj ] = true
252- }
275+ func checkProjData (wantProjData map [string ][]* RowData ) error {
276+ var errs multiError
253277 for proj := range projRds {
254- if ! wantProj [proj ] {
255- t . Errorf ("project in exporter's project data not wanted: %s" , proj )
278+ if _ , ok := wantProjData [proj ]; ! ok {
279+ errs . addf ("project in exporter's project data not wanted: %s" , proj )
256280 }
257281 }
258282
259283 for proj , wantRds := range wantProjData {
260284 rds , ok := projRds [proj ]
261285 if ! ok {
262- t . Errorf ("wanted project not found in exporter's project data: %v" , proj )
286+ errs . addf ("wanted project not found in exporter's project data: %v" , proj )
263287 continue
264288 }
265289 if err := checkRowDataArr (* rds , wantRds ); err != nil {
266- t . Errorf ("RowData array mismatch for project %s: %v" , proj , err )
290+ errs . addf ("RowData array mismatch for project %s: %v" , proj , err )
267291 }
268292 }
293+ return errs .toError ()
269294}
270295
271296// checkLabels checks data in labels.
272- func checkLabels (t * testing.T , prefix string , labels , wantLabels map [string ]string ) {
297+ func checkLabels (prefix string , labels , wantLabels map [string ]string ) error {
298+ var errs multiError
273299 for labelName , value := range labels {
274300 wantValue , ok := wantLabels [labelName ]
275301 if ! ok {
276- t . Errorf ("%s: label name in time series not wanted: %s" , prefix , labelName )
302+ errs . addf ("%s: label name in time series not wanted: %s" , prefix , labelName )
277303 continue
278304 }
279305 if value != wantValue {
280- t . Errorf ("%s: value for label name %s got: %s, want: %s" , prefix , labelName , value , wantValue )
306+ errs . addf ("%s: value for label name %s got: %s, want: %s" , prefix , labelName , value , wantValue )
281307 }
282308 }
283309 for wantLabelName := range wantLabels {
284310 if _ , ok := labels [wantLabelName ]; ! ok {
285- t . Errorf ("%s: wanted label name not found in time series: %s" , prefix , wantLabelName )
311+ errs . addf ("%s: wanted label name not found in time series: %s" , prefix , wantLabelName )
286312 }
287313 }
314+ return errs .toError ()
288315}
0 commit comments