github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/command/v6/shared/app_summary_displayer_refactored_test.go (about)

     1  package shared_test
     2  
     3  import (
     4  	"time"
     5  
     6  	"code.cloudfoundry.org/cli/actor/v2action"
     7  	"code.cloudfoundry.org/cli/actor/v2v3action"
     8  	"code.cloudfoundry.org/cli/actor/v3action"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    10  	. "code.cloudfoundry.org/cli/command/v6/shared"
    11  	"code.cloudfoundry.org/cli/integration/helpers"
    12  	"code.cloudfoundry.org/cli/types"
    13  	"code.cloudfoundry.org/cli/util/ui"
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  	. "github.com/onsi/gomega/gbytes"
    17  )
    18  
    19  var _ = Describe("app summary displayer", func() {
    20  	var (
    21  		appSummaryDisplayer *AppSummaryDisplayer2
    22  		output              *Buffer
    23  		testUI              *ui.UI
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		output = NewBuffer()
    28  		testUI = ui.NewTestUI(nil, output, NewBuffer())
    29  
    30  		appSummaryDisplayer = NewAppSummaryDisplayer2(testUI)
    31  	})
    32  
    33  	Describe("AppDisplay", func() {
    34  		var (
    35  			summary             v2v3action.ApplicationSummary
    36  			displayStartCommand bool
    37  		)
    38  
    39  		JustBeforeEach(func() {
    40  			appSummaryDisplayer.AppDisplay(summary, displayStartCommand)
    41  		})
    42  
    43  		When("the app has instances", func() {
    44  			When("the process instances are running", func() {
    45  				var uptime time.Duration
    46  
    47  				BeforeEach(func() {
    48  					uptime = time.Now().Sub(time.Unix(267321600, 0))
    49  					summary = v2v3action.ApplicationSummary{
    50  						ApplicationSummary: v3action.ApplicationSummary{
    51  							Application: v3action.Application{
    52  								GUID:  "some-app-guid",
    53  								State: constant.ApplicationStarted,
    54  							},
    55  							ProcessSummaries: v3action.ProcessSummaries{
    56  								{
    57  									Process: v3action.Process{
    58  										Type:       constant.ProcessTypeWeb,
    59  										MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
    60  										DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
    61  									},
    62  									InstanceDetails: []v3action.ProcessInstance{
    63  										v3action.ProcessInstance{
    64  											Index:       0,
    65  											State:       constant.ProcessInstanceRunning,
    66  											MemoryUsage: 1000000,
    67  											DiskUsage:   1000000,
    68  											MemoryQuota: 33554432,
    69  											DiskQuota:   2000000,
    70  											Uptime:      int(uptime.Seconds()),
    71  											Details:     "Some Details 1",
    72  										},
    73  										v3action.ProcessInstance{
    74  											Index:       1,
    75  											State:       constant.ProcessInstanceRunning,
    76  											MemoryUsage: 2000000,
    77  											DiskUsage:   2000000,
    78  											MemoryQuota: 33554432,
    79  											DiskQuota:   4000000,
    80  											Uptime:      int(time.Now().Sub(time.Unix(330480000, 0)).Seconds()),
    81  											Details:     "Some Details 2",
    82  										},
    83  										v3action.ProcessInstance{
    84  											Index:       2,
    85  											State:       constant.ProcessInstanceRunning,
    86  											MemoryUsage: 3000000,
    87  											DiskUsage:   3000000,
    88  											MemoryQuota: 33554432,
    89  											DiskQuota:   6000000,
    90  											Uptime:      int(time.Now().Sub(time.Unix(1277164800, 0)).Seconds()),
    91  										},
    92  									},
    93  								},
    94  								{
    95  									Process: v3action.Process{
    96  										Type:       "console",
    97  										MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
    98  										DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
    99  									},
   100  									InstanceDetails: []v3action.ProcessInstance{
   101  										v3action.ProcessInstance{
   102  											Index:       0,
   103  											State:       constant.ProcessInstanceRunning,
   104  											MemoryUsage: 1000000,
   105  											DiskUsage:   1000000,
   106  											MemoryQuota: 33554432,
   107  											DiskQuota:   8000000,
   108  											Uptime:      int(time.Now().Sub(time.Unix(167572800, 0)).Seconds()),
   109  										},
   110  									},
   111  								},
   112  							},
   113  						},
   114  					}
   115  				})
   116  
   117  				It("lists information for each of the processes", func() {
   118  					processTable := helpers.ParseV3AppProcessTable(output.Contents())
   119  					Expect(len(processTable.Processes)).To(Equal(2))
   120  
   121  					webProcessSummary := processTable.Processes[0]
   122  					Expect(webProcessSummary.Type).To(Equal("web"))
   123  					Expect(webProcessSummary.InstanceCount).To(Equal("3/3"))
   124  					Expect(webProcessSummary.MemUsage).To(Equal("32M"))
   125  
   126  					Expect(webProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   127  					Expect(webProcessSummary.Instances[0].Since).To(MatchRegexp(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z`))
   128  					Expect(time.Parse(time.RFC3339, webProcessSummary.Instances[0].Since)).To(BeTemporally("~", time.Now().Add(-uptime), 2*time.Second))
   129  					Expect(webProcessSummary.Instances[0].Disk).To(Equal("976.6K of 1.9M"))
   130  					Expect(webProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   131  					Expect(webProcessSummary.Instances[0].Details).To(Equal("Some Details 1"))
   132  
   133  					Expect(webProcessSummary.Instances[1].Memory).To(Equal("1.9M of 32M"))
   134  					Expect(webProcessSummary.Instances[1].Disk).To(Equal("1.9M of 3.8M"))
   135  					Expect(webProcessSummary.Instances[1].CPU).To(Equal("0.0%"))
   136  					Expect(webProcessSummary.Instances[1].Details).To(Equal("Some Details 2"))
   137  
   138  					Expect(webProcessSummary.Instances[2].Memory).To(Equal("2.9M of 32M"))
   139  					Expect(webProcessSummary.Instances[2].Disk).To(Equal("2.9M of 5.7M"))
   140  					Expect(webProcessSummary.Instances[2].CPU).To(Equal("0.0%"))
   141  
   142  					consoleProcessSummary := processTable.Processes[1]
   143  					Expect(consoleProcessSummary.Type).To(Equal("console"))
   144  					Expect(consoleProcessSummary.InstanceCount).To(Equal("1/1"))
   145  					Expect(consoleProcessSummary.MemUsage).To(Equal("16M"))
   146  
   147  					Expect(consoleProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   148  					Expect(consoleProcessSummary.Instances[0].Disk).To(Equal("976.6K of 7.6M"))
   149  					Expect(consoleProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   150  				})
   151  			})
   152  
   153  			When("when a process has 0 instances", func() {
   154  				BeforeEach(func() {
   155  					summary = v2v3action.ApplicationSummary{
   156  						ApplicationSummary: v3action.ApplicationSummary{
   157  							Application: v3action.Application{
   158  								GUID:  "some-app-guid",
   159  								State: constant.ApplicationStarted,
   160  							},
   161  							ProcessSummaries: v3action.ProcessSummaries{
   162  								{
   163  									Process: v3action.Process{
   164  										Type:       constant.ProcessTypeWeb,
   165  										MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   166  										DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
   167  									},
   168  									InstanceDetails: []v3action.ProcessInstance{
   169  										v3action.ProcessInstance{
   170  											Index:       0,
   171  											State:       constant.ProcessInstanceRunning,
   172  											MemoryUsage: 1000000,
   173  											DiskUsage:   1000000,
   174  											MemoryQuota: 33554432,
   175  											DiskQuota:   2000000,
   176  											Uptime:      int(time.Now().Sub(time.Unix(267321600, 0)).Seconds()),
   177  										},
   178  									},
   179  								},
   180  								{
   181  									Process: v3action.Process{
   182  										Type:       "console",
   183  										MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
   184  										DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
   185  									},
   186  								},
   187  							},
   188  						},
   189  					}
   190  				})
   191  
   192  				It("does not show the instances table for that process", func() {
   193  					Expect(testUI.Out).To(Say(`type:\s+web`))
   194  					Expect(testUI.Out).To(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   195  					Expect(testUI.Out).To(Say(`type:\s+console`))
   196  					Expect(testUI.Out).To(Say(`There are no running instances of this process.`))
   197  				})
   198  			})
   199  
   200  			When("all the instances for a processes are down", func() {
   201  				BeforeEach(func() {
   202  					summary = v2v3action.ApplicationSummary{
   203  						ApplicationSummary: v3action.ApplicationSummary{
   204  							ProcessSummaries: []v3action.ProcessSummary{
   205  								{
   206  									Process: v3action.Process{
   207  										Type:       constant.ProcessTypeWeb,
   208  										MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   209  									},
   210  									InstanceDetails: []v3action.ProcessInstance{{State: constant.ProcessInstanceDown}},
   211  								},
   212  							},
   213  						},
   214  					}
   215  				})
   216  
   217  				It("displays the instance table", func() {
   218  					Expect(testUI.Out).To(Say(`type:\s+web`))
   219  					Expect(testUI.Out).To(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   220  				})
   221  			})
   222  
   223  			Describe("start command", func() {
   224  				BeforeEach(func() {
   225  					summary = v2v3action.ApplicationSummary{
   226  						ApplicationSummary: v3action.ApplicationSummary{
   227  							Application: v3action.Application{
   228  								GUID:  "some-app-guid",
   229  								State: constant.ApplicationStarted,
   230  							},
   231  							ProcessSummaries: v3action.ProcessSummaries{
   232  								{
   233  									Process: v3action.Process{
   234  										Type:    constant.ProcessTypeWeb,
   235  										Command: *types.NewFilteredString("some-command-1"),
   236  									},
   237  								},
   238  								{
   239  									Process: v3action.Process{
   240  										Type:    "console",
   241  										Command: *types.NewFilteredString("some-command-2"),
   242  									},
   243  								},
   244  								{
   245  									Process: v3action.Process{
   246  										Type: "random",
   247  									},
   248  								},
   249  							},
   250  						},
   251  					}
   252  				})
   253  
   254  				When("displayStartCommand is true", func() {
   255  					BeforeEach(func() {
   256  						displayStartCommand = true
   257  					})
   258  
   259  					It("displays the non-empty start command for each process", func() {
   260  						Expect(testUI.Out).To(Say(`type:\s+web`))
   261  						Expect(testUI.Out).To(Say(`start command:\s+some-command-1`))
   262  
   263  						Expect(testUI.Out).To(Say(`type:\s+console`))
   264  						Expect(testUI.Out).To(Say(`start command:\s+some-command-2`))
   265  
   266  						Expect(testUI.Out).To(Say(`type:\s+random`))
   267  						Expect(testUI.Out).ToNot(Say("start command:"))
   268  					})
   269  				})
   270  
   271  				When("displayStartCommand is false", func() {
   272  					BeforeEach(func() {
   273  						displayStartCommand = false
   274  					})
   275  
   276  					It("hides the start command", func() {
   277  						Expect(testUI.Out).ToNot(Say("start command:"))
   278  					})
   279  				})
   280  			})
   281  		})
   282  
   283  		When("the app has no instances", func() {
   284  			BeforeEach(func() {
   285  				summary = v2v3action.ApplicationSummary{
   286  					ApplicationSummary: v3action.ApplicationSummary{
   287  						Application: v3action.Application{
   288  							GUID:  "some-app-guid",
   289  							State: constant.ApplicationStarted,
   290  						},
   291  						ProcessSummaries: v3action.ProcessSummaries{
   292  							{
   293  								Process: v3action.Process{
   294  									Type:       constant.ProcessTypeWeb,
   295  									MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   296  									DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
   297  								},
   298  							},
   299  							{
   300  								Process: v3action.Process{
   301  									Type:       "console",
   302  									MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
   303  									DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
   304  								},
   305  							},
   306  						},
   307  					},
   308  				}
   309  			})
   310  
   311  			It("lists information for each of the processes", func() {
   312  				Expect(testUI.Out).To(Say(`type:\s+web`))
   313  				Expect(testUI.Out).To(Say(`instances:\s+0/0`))
   314  				Expect(testUI.Out).To(Say(`memory usage:\s+32M`))
   315  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   316  
   317  				Expect(testUI.Out).To(Say(`type:\s+console`))
   318  				Expect(testUI.Out).To(Say(`instances:\s+0/0`))
   319  				Expect(testUI.Out).To(Say(`memory usage:\s+16M`))
   320  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   321  			})
   322  
   323  			It("does not display the instance table", func() {
   324  				Expect(testUI.Out).NotTo(Say(`state\s+since\s+cpu\s+memory\s+disk`))
   325  			})
   326  		})
   327  
   328  		When("the app is stopped", func() {
   329  			BeforeEach(func() {
   330  				summary = v2v3action.ApplicationSummary{
   331  					ApplicationSummary: v3action.ApplicationSummary{
   332  						Application: v3action.Application{
   333  							GUID:  "some-app-guid",
   334  							State: constant.ApplicationStopped,
   335  						},
   336  						ProcessSummaries: v3action.ProcessSummaries{
   337  							{
   338  								Process: v3action.Process{
   339  									Type: constant.ProcessTypeWeb,
   340  								},
   341  							},
   342  							{
   343  								Process: v3action.Process{
   344  									Type: "console",
   345  								},
   346  							},
   347  						},
   348  					},
   349  				}
   350  			})
   351  
   352  			It("lists information for each of the processes", func() {
   353  				Expect(testUI.Out).To(Say(`type:\s+web`))
   354  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   355  
   356  				Expect(testUI.Out).To(Say(`type:\s+console`))
   357  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   358  			})
   359  
   360  			It("does not display the instance table", func() {
   361  				Expect(testUI.Out).NotTo(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   362  			})
   363  		})
   364  
   365  		Describe("isolation segments", func() {
   366  			When("the isolation segment name is provided", func() {
   367  				var isolationSegmentName string
   368  				BeforeEach(func() {
   369  					isolationSegmentName = "potato beans"
   370  					summary.ApplicationInstanceWithStats =
   371  						[]v2action.ApplicationInstanceWithStats{
   372  							{IsolationSegment: isolationSegmentName},
   373  						}
   374  				})
   375  
   376  				It("should output the isolation segment name", func() {
   377  					Expect(testUI.Out).To(Say(`isolation segment:\s+%s`, isolationSegmentName))
   378  				})
   379  			})
   380  
   381  			When("the application summary has no isolation segment information", func() {
   382  				BeforeEach(func() {
   383  					summary = v2v3action.ApplicationSummary{
   384  						ApplicationSummary: v3action.ApplicationSummary{
   385  							Application: v3action.Application{
   386  								GUID:  "some-app-guid",
   387  								State: constant.ApplicationStopped,
   388  							},
   389  						},
   390  					}
   391  				})
   392  
   393  				It("should not output isolation segment header", func() {
   394  					Expect(testUI.Out).ToNot(Say("isolation segment:"))
   395  				})
   396  			})
   397  		})
   398  
   399  		Describe("last upload time", func() {
   400  			When("the application has a last uploaded time", func() {
   401  				var createdTime string
   402  
   403  				BeforeEach(func() {
   404  					createdTime = "2006-01-02T15:04:05-07:00"
   405  					summary.CurrentDroplet.CreatedAt = createdTime
   406  				})
   407  
   408  				It("displays the uploaded time", func() {
   409  					t, err := time.Parse(time.RFC3339, createdTime)
   410  					Expect(err).To(Not(HaveOccurred()))
   411  
   412  					time := t.Local().Format("Mon 02 Jan 15:04:05 MST 2006")
   413  					Expect(testUI.Out).To(Say(`last uploaded:\s+%s`, time))
   414  				})
   415  			})
   416  
   417  			When("the application does not have a last uploaded time", func() {
   418  				BeforeEach(func() {
   419  					summary.CurrentDroplet.CreatedAt = ""
   420  				})
   421  
   422  				It("leaves last uploaded blank", func() {
   423  					Expect(testUI.Out).To(Say(`(?m)last uploaded:\s*\n`))
   424  				})
   425  			})
   426  		})
   427  
   428  		When("the application has routes", func() {
   429  			BeforeEach(func() {
   430  				summary.Routes = []v2action.Route{
   431  					{Host: "route1", Domain: v2action.Domain{Name: "example.com"}},
   432  					{Host: "route2", Domain: v2action.Domain{Name: "example.com"}},
   433  				}
   434  			})
   435  
   436  			It("displays routes", func() {
   437  				Expect(testUI.Out).To(Say(`routes:\s+%s, %s`, "route1.example.com", "route2.example.com"))
   438  			})
   439  		})
   440  
   441  		When("the application has a stack", func() {
   442  			BeforeEach(func() {
   443  				summary.CurrentDroplet.Stack = "some-stack"
   444  			})
   445  
   446  			It("displays stack", func() {
   447  				Expect(testUI.Out).To(Say(`stack:\s+some-stack`))
   448  			})
   449  		})
   450  
   451  		When("the application is a docker app", func() {
   452  			BeforeEach(func() {
   453  				summary = v2v3action.ApplicationSummary{
   454  					ApplicationSummary: v3action.ApplicationSummary{
   455  						Application: v3action.Application{
   456  							GUID:          "some-guid",
   457  							Name:          "some-app",
   458  							State:         constant.ApplicationStarted,
   459  							LifecycleType: constant.AppLifecycleTypeDocker,
   460  						},
   461  						CurrentDroplet: v3action.Droplet{
   462  							Image: "docker/some-image",
   463  						},
   464  					},
   465  				}
   466  			})
   467  
   468  			It("displays the app information", func() {
   469  				Expect(testUI.Out).To(Say(`name:\s+some-app`))
   470  				Expect(testUI.Out).To(Say(`requested state:\s+started`))
   471  				Expect(testUI.Out).To(Say(`routes:\s+\n`))
   472  				Expect(testUI.Out).To(Say(`stack:\s+\n`))
   473  				Expect(testUI.Out).To(Say(`(?m)docker image:\s+docker/some-image$\n`))
   474  			})
   475  		})
   476  
   477  		When("the application is a buildpack app", func() {
   478  			BeforeEach(func() {
   479  				summary = v2v3action.ApplicationSummary{
   480  					ApplicationSummary: v3action.ApplicationSummary{
   481  						CurrentDroplet: v3action.Droplet{
   482  							Stack: "cflinuxfs2",
   483  							Buildpacks: []v3action.Buildpack{
   484  								{
   485  									Name:         "ruby_buildpack",
   486  									DetectOutput: "some-detect-output",
   487  								},
   488  								{
   489  									Name:         "some-buildpack",
   490  									DetectOutput: "",
   491  								},
   492  							},
   493  						},
   494  					},
   495  				}
   496  			})
   497  
   498  			It("displays stack and buildpacks", func() {
   499  				Expect(testUI.Out).To(Say(`stack:\s+cflinuxfs2`))
   500  				Expect(testUI.Out).To(Say(`buildpacks:\s+some-detect-output, some-buildpack`))
   501  			})
   502  		})
   503  	})
   504  })