@@ -6,6 +6,7 @@ package status
66import (
77 "bytes"
88 "context"
9+ "encoding/json"
910 "strings"
1011 "testing"
1112 "time"
@@ -53,6 +54,23 @@ metadata:
5354 }
5455)
5556
57+ type fakePoller struct {
58+ events []pollevent.Event
59+ }
60+
61+ func (f * fakePoller ) Poll (ctx context.Context , _ object.ObjMetadataSet ,
62+ _ polling.PollOptions ) <- chan pollevent.Event {
63+ eventChannel := make (chan pollevent.Event )
64+ go func () {
65+ defer close (eventChannel )
66+ for _ , e := range f .events {
67+ eventChannel <- e
68+ }
69+ <- ctx .Done ()
70+ }()
71+ return eventChannel
72+ }
73+
5674func TestCommand (t * testing.T ) {
5775 testCases := map [string ]struct {
5876 pollUntil string
@@ -217,6 +235,261 @@ foo/deployment.apps/default/foo is InProgress: inProgress
217235 },
218236 }
219237
238+ jsonTestCases := map [string ]struct {
239+ pollUntil string
240+ printer string
241+ timeout time.Duration
242+ input string
243+ inventory object.ObjMetadataSet
244+ events []pollevent.Event
245+ expectedErrMsg string
246+ expectedOutput []map [string ]interface {}
247+ }{
248+ "wait for all known json" : {
249+ pollUntil : "known" ,
250+ printer : "json" ,
251+ input : inventoryTemplate ,
252+ inventory : object.ObjMetadataSet {
253+ depObject ,
254+ stsObject ,
255+ },
256+ events : []pollevent.Event {
257+ {
258+ Type : pollevent .ResourceUpdateEvent ,
259+ Resource : & pollevent.ResourceStatus {
260+ Identifier : depObject ,
261+ Status : status .InProgressStatus ,
262+ Message : "inProgress" ,
263+ },
264+ },
265+ {
266+ Type : pollevent .ResourceUpdateEvent ,
267+ Resource : & pollevent.ResourceStatus {
268+ Identifier : stsObject ,
269+ Status : status .CurrentStatus ,
270+ Message : "current" ,
271+ },
272+ },
273+ },
274+ expectedOutput : []map [string ]interface {}{
275+ {
276+ "group" : "apps" ,
277+ "kind" : "Deployment" ,
278+ "namespace" : "default" ,
279+ "name" : "foo" ,
280+ "timestamp" : "" ,
281+ "type" : "status" ,
282+ "inventory-name" : "foo" ,
283+ "status" : "InProgress" ,
284+ "message" : "inProgress" ,
285+ },
286+ {
287+ "group" : "apps" ,
288+ "kind" : "StatefulSet" ,
289+ "namespace" : "default" ,
290+ "name" : "bar" ,
291+ "timestamp" : "" ,
292+ "type" : "status" ,
293+ "inventory-name" : "foo" ,
294+ "status" : "Current" ,
295+ "message" : "current" ,
296+ },
297+ },
298+ },
299+ "wait for all current json" : {
300+ pollUntil : "current" ,
301+ printer : "json" ,
302+ input : inventoryTemplate ,
303+ inventory : object.ObjMetadataSet {
304+ depObject ,
305+ stsObject ,
306+ },
307+ events : []pollevent.Event {
308+ {
309+ Type : pollevent .ResourceUpdateEvent ,
310+ Resource : & pollevent.ResourceStatus {
311+ Identifier : depObject ,
312+ Status : status .InProgressStatus ,
313+ Message : "inProgress" ,
314+ },
315+ },
316+ {
317+ Type : pollevent .ResourceUpdateEvent ,
318+ Resource : & pollevent.ResourceStatus {
319+ Identifier : stsObject ,
320+ Status : status .InProgressStatus ,
321+ Message : "inProgress" ,
322+ },
323+ },
324+ {
325+ Type : pollevent .ResourceUpdateEvent ,
326+ Resource : & pollevent.ResourceStatus {
327+ Identifier : stsObject ,
328+ Status : status .CurrentStatus ,
329+ Message : "current" ,
330+ },
331+ },
332+ {
333+ Type : pollevent .ResourceUpdateEvent ,
334+ Resource : & pollevent.ResourceStatus {
335+ Identifier : depObject ,
336+ Status : status .CurrentStatus ,
337+ Message : "current" ,
338+ },
339+ },
340+ },
341+ expectedOutput : []map [string ]interface {}{
342+ {
343+ "group" : "apps" ,
344+ "kind" : "Deployment" ,
345+ "namespace" : "default" ,
346+ "name" : "foo" ,
347+ "timestamp" : "" ,
348+ "type" : "status" ,
349+ "inventory-name" : "foo" ,
350+ "status" : "InProgress" ,
351+ "message" : "inProgress" ,
352+ },
353+ {
354+ "group" : "apps" ,
355+ "kind" : "StatefulSet" ,
356+ "namespace" : "default" ,
357+ "name" : "bar" ,
358+ "timestamp" : "" ,
359+ "type" : "status" ,
360+ "inventory-name" : "foo" ,
361+ "status" : "InProgress" ,
362+ "message" : "inProgress" ,
363+ },
364+ {
365+ "group" : "apps" ,
366+ "kind" : "StatefulSet" ,
367+ "namespace" : "default" ,
368+ "name" : "bar" ,
369+ "timestamp" : "" ,
370+ "type" : "status" ,
371+ "inventory-name" : "foo" ,
372+ "status" : "Current" ,
373+ "message" : "current" ,
374+ },
375+ {
376+ "group" : "apps" ,
377+ "kind" : "Deployment" ,
378+ "namespace" : "default" ,
379+ "name" : "foo" ,
380+ "timestamp" : "" ,
381+ "type" : "status" ,
382+ "inventory-name" : "foo" ,
383+ "status" : "Current" ,
384+ "message" : "current" ,
385+ },
386+ },
387+ },
388+ "wait for all deleted json" : {
389+ pollUntil : "deleted" ,
390+ printer : "json" ,
391+ input : inventoryTemplate ,
392+ inventory : object.ObjMetadataSet {
393+ depObject ,
394+ stsObject ,
395+ },
396+ events : []pollevent.Event {
397+ {
398+ Type : pollevent .ResourceUpdateEvent ,
399+ Resource : & pollevent.ResourceStatus {
400+ Identifier : stsObject ,
401+ Status : status .NotFoundStatus ,
402+ Message : "notFound" ,
403+ },
404+ },
405+ {
406+ Type : pollevent .ResourceUpdateEvent ,
407+ Resource : & pollevent.ResourceStatus {
408+ Identifier : depObject ,
409+ Status : status .NotFoundStatus ,
410+ Message : "notFound" ,
411+ },
412+ },
413+ },
414+ expectedOutput : []map [string ]interface {}{
415+ {
416+ "group" : "apps" ,
417+ "kind" : "StatefulSet" ,
418+ "namespace" : "default" ,
419+ "name" : "bar" ,
420+ "timestamp" : "" ,
421+ "type" : "status" ,
422+ "inventory-name" : "foo" ,
423+ "status" : "NotFound" ,
424+ "message" : "notFound" ,
425+ },
426+ {
427+ "group" : "apps" ,
428+ "kind" : "Deployment" ,
429+ "namespace" : "default" ,
430+ "name" : "foo" ,
431+ "timestamp" : "" ,
432+ "type" : "status" ,
433+ "inventory-name" : "foo" ,
434+ "status" : "NotFound" ,
435+ "message" : "notFound" ,
436+ },
437+ },
438+ },
439+ "forever with timeout json" : {
440+ pollUntil : "forever" ,
441+ printer : "json" ,
442+ timeout : 2 * time .Second ,
443+ input : inventoryTemplate ,
444+ inventory : object.ObjMetadataSet {
445+ depObject ,
446+ stsObject ,
447+ },
448+ events : []pollevent.Event {
449+ {
450+ Type : pollevent .ResourceUpdateEvent ,
451+ Resource : & pollevent.ResourceStatus {
452+ Identifier : stsObject ,
453+ Status : status .InProgressStatus ,
454+ Message : "inProgress" ,
455+ },
456+ },
457+ {
458+ Type : pollevent .ResourceUpdateEvent ,
459+ Resource : & pollevent.ResourceStatus {
460+ Identifier : depObject ,
461+ Status : status .InProgressStatus ,
462+ Message : "inProgress" ,
463+ },
464+ },
465+ },
466+ expectedOutput : []map [string ]interface {}{
467+ {
468+ "group" : "apps" ,
469+ "kind" : "StatefulSet" ,
470+ "namespace" : "default" ,
471+ "name" : "bar" ,
472+ "timestamp" : "" ,
473+ "type" : "status" ,
474+ "inventory-name" : "foo" ,
475+ "status" : "InProgress" ,
476+ "message" : "inProgress" ,
477+ },
478+ {
479+ "group" : "apps" ,
480+ "kind" : "Deployment" ,
481+ "namespace" : "default" ,
482+ "name" : "foo" ,
483+ "timestamp" : "" ,
484+ "type" : "status" ,
485+ "inventory-name" : "foo" ,
486+ "status" : "InProgress" ,
487+ "message" : "inProgress" ,
488+ },
489+ },
490+ },
491+ }
492+
220493 for tn , tc := range testCases {
221494 t .Run (tn , func (t * testing.T ) {
222495 tf := cmdtesting .NewTestFactory ().WithNamespace ("namespace" )
@@ -258,21 +531,75 @@ foo/deployment.apps/default/foo is InProgress: inProgress
258531 assert .Equal (t , strings .TrimSpace (buf .String ()), strings .TrimSpace (tc .expectedOutput ))
259532 })
260533 }
261- }
262534
263- type fakePoller struct {
264- events []pollevent.Event
535+ for tn , tc := range jsonTestCases {
536+ t .Run (tn , func (t * testing.T ) {
537+ tf := cmdtesting .NewTestFactory ().WithNamespace ("namespace" )
538+ defer tf .Cleanup ()
539+
540+ loader := manifestreader .NewFakeLoader (tf , tc .inventory )
541+ runner := & Runner {
542+ factory : tf ,
543+ invFactory : inventory .FakeClientFactory (tc .inventory ),
544+ loader : loader ,
545+ pollerFactoryFunc : func (c cmdutil.Factory ) (poller.Poller , error ) {
546+ return & fakePoller {tc .events }, nil
547+ },
548+
549+ pollUntil : tc .pollUntil ,
550+ output : tc .printer ,
551+ timeout : tc .timeout ,
552+ }
553+
554+ cmd := & cobra.Command {
555+ RunE : runner .runE ,
556+ }
557+ cmd .SetIn (strings .NewReader (tc .input ))
558+ var buf bytes.Buffer
559+ cmd .SetOut (& buf )
560+ cmd .SetArgs ([]string {})
561+
562+ err := cmd .Execute ()
563+ if tc .expectedErrMsg != "" {
564+ if ! assert .Error (t , err ) {
565+ t .FailNow ()
566+ }
567+ assert .Contains (t , err .Error (), tc .expectedErrMsg )
568+ return
569+ }
570+
571+ assert .NoError (t , err )
572+ actual := strings .Split (buf .String (), "\n " )
573+ assertOutput (t , tc .expectedOutput , actual )
574+ })
575+ }
265576}
266577
267- func (f * fakePoller ) Poll (ctx context.Context , _ object.ObjMetadataSet ,
268- _ polling.PollOptions ) <- chan pollevent.Event {
269- eventChannel := make (chan pollevent.Event )
270- go func () {
271- defer close (eventChannel )
272- for _ , e := range f .events {
273- eventChannel <- e
578+ // nolint:unparam
579+ func assertOutput (t * testing.T , expectedOutput []map [string ]interface {}, actual []string ) bool {
580+ for i , expectedMap := range expectedOutput {
581+ if len (expectedMap ) == 0 {
582+ return assert .Empty (t , actual [i ])
274583 }
275- <- ctx .Done ()
276- }()
277- return eventChannel
584+
585+ var m map [string ]interface {}
586+ err := json .Unmarshal ([]byte (actual [i ]), & m )
587+ if ! assert .NoError (t , err ) {
588+ return false
589+ }
590+
591+ if _ , found := expectedMap ["timestamp" ]; found {
592+ if _ , ok := m ["timestamp" ]; ok {
593+ delete (expectedMap , "timestamp" )
594+ delete (m , "timestamp" )
595+ } else {
596+ t .Error ("expected to find key 'timestamp', but didn't" )
597+ return false
598+ }
599+ }
600+ if ! assert .Equal (t , expectedMap , m ) {
601+ return false
602+ }
603+ }
604+ return true
278605}
0 commit comments