github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/actor/loggingaction/logging_test.go (about)

     1  package loggingaction_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	"code.cloudfoundry.org/cli/actor/loggingaction"
    10  
    11  	"code.cloudfoundry.org/cli/actor/loggingaction/loggingactionfakes"
    12  	"code.cloudfoundry.org/go-loggregator/rpc/loggregator_v2"
    13  	logcache "code.cloudfoundry.org/log-cache/pkg/client"
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  )
    17  
    18  var _ = Describe("Logging Actions", func() {
    19  	var (
    20  		fakeLogCacheClient *loggingactionfakes.FakeLogCacheClient
    21  	)
    22  
    23  	BeforeEach(func() {
    24  		fakeLogCacheClient = new(loggingactionfakes.FakeLogCacheClient)
    25  	})
    26  
    27  	Describe("LogMessage", func() {
    28  		Describe("Staging", func() {
    29  			When("the log is a staging log", func() {
    30  				It("returns true", func() {
    31  					message := loggingaction.LogMessage{SourceType: "STG"}
    32  					Expect(message.Staging()).To(BeTrue())
    33  				})
    34  			})
    35  
    36  			When("the log is any other kind of log", func() {
    37  				It("returns false", func() {
    38  					message := loggingaction.LogMessage{SourceType: "APP"}
    39  					Expect(message.Staging()).To(BeFalse())
    40  				})
    41  			})
    42  		})
    43  	})
    44  
    45  	Describe("GetStreamingLogs", func() {
    46  		var (
    47  			expectedAppGUID string
    48  
    49  			messages      <-chan loggingaction.LogMessage
    50  			errs          <-chan error
    51  			stopStreaming context.CancelFunc
    52  		)
    53  
    54  		BeforeEach(func() {
    55  			expectedAppGUID = "some-app-guid"
    56  		})
    57  
    58  		AfterEach(func() {
    59  			Eventually(messages).Should(BeClosed())
    60  			Eventually(errs).Should(BeClosed())
    61  		})
    62  
    63  		JustBeforeEach(func() {
    64  			messages, errs, stopStreaming = loggingaction.GetStreamingLogs(expectedAppGUID, fakeLogCacheClient)
    65  		})
    66  
    67  		When("receiving logs", func() {
    68  			BeforeEach(func() {
    69  				fakeLogCacheClient.ReadStub = func(
    70  					ctx context.Context,
    71  					sourceID string,
    72  					start time.Time,
    73  					opts ...logcache.ReadOption,
    74  				) ([]*loggregator_v2.Envelope, error) {
    75  					if fakeLogCacheClient.ReadCallCount() > 2 {
    76  						stopStreaming()
    77  					}
    78  
    79  					return []*loggregator_v2.Envelope{{
    80  						// 2 seconds in the past to get past Walk delay
    81  						Timestamp:  time.Now().Add(-3 * time.Second).UnixNano(),
    82  						SourceId:   "some-app-guid",
    83  						InstanceId: "some-source-instance",
    84  						Message: &loggregator_v2.Envelope_Log{
    85  							Log: &loggregator_v2.Log{
    86  								Payload: []byte("message-1"),
    87  								Type:    loggregator_v2.Log_OUT,
    88  							},
    89  						},
    90  						Tags: map[string]string{
    91  							"source_type": "some-source-type",
    92  						},
    93  					}, {
    94  						// 2 seconds in the past to get past Walk delay
    95  						Timestamp:  time.Now().Add(-2 * time.Second).UnixNano(),
    96  						SourceId:   "some-app-guid",
    97  						InstanceId: "some-source-instance",
    98  						Message: &loggregator_v2.Envelope_Log{
    99  							Log: &loggregator_v2.Log{
   100  								Payload: []byte("message-2"),
   101  								Type:    loggregator_v2.Log_OUT,
   102  							},
   103  						},
   104  						Tags: map[string]string{
   105  							"source_type": "some-source-type",
   106  						},
   107  					}}, ctx.Err()
   108  				}
   109  			})
   110  
   111  			It("converts them to log messages, sorts them, and passes them through the messages channel", func() {
   112  				Eventually(messages).Should(HaveLen(4))
   113  				var message loggingaction.LogMessage
   114  				Expect(messages).To(Receive(&message))
   115  				Expect(message.Message).To(Equal("message-1"))
   116  				Expect(messages).To(Receive(&message))
   117  				Expect(message.Message).To(Equal("message-2"))
   118  
   119  				Expect(errs).ToNot(Receive())
   120  			})
   121  		})
   122  
   123  		When("logs are older than 5 seconds", func() {
   124  			var readStart chan time.Time
   125  
   126  			BeforeEach(func() {
   127  				readStart = make(chan time.Time, 100)
   128  				fakeLogCacheClient.ReadStub = func(
   129  					ctx context.Context,
   130  					sourceID string,
   131  					start time.Time,
   132  					opts ...logcache.ReadOption,
   133  				) ([]*loggregator_v2.Envelope, error) {
   134  					if fakeLogCacheClient.ReadCallCount() > 1 {
   135  						stopStreaming()
   136  					}
   137  
   138  					readStart <- start
   139  
   140  					return []*loggregator_v2.Envelope{{
   141  						// 2 seconds in the past to get past Walk delay
   142  						Timestamp:  time.Now().Add(-6 * time.Second).UnixNano(),
   143  						SourceId:   "some-app-guid",
   144  						InstanceId: "some-source-instance",
   145  						Message: &loggregator_v2.Envelope_Log{
   146  							Log: &loggregator_v2.Log{
   147  								Payload: []byte("message-1"),
   148  								Type:    loggregator_v2.Log_OUT,
   149  							},
   150  						},
   151  						Tags: map[string]string{
   152  							"source_type": "some-source-type",
   153  						},
   154  					}, {
   155  						// 2 seconds in the past to get past Walk delay
   156  						Timestamp:  time.Now().Add(-2 * time.Second).UnixNano(),
   157  						SourceId:   "some-app-guid",
   158  						InstanceId: "some-source-instance",
   159  						Message: &loggregator_v2.Envelope_Log{
   160  							Log: &loggregator_v2.Log{
   161  								Payload: []byte("message-2"),
   162  								Type:    loggregator_v2.Log_OUT,
   163  							},
   164  						},
   165  						Tags: map[string]string{
   166  							"source_type": "some-source-type",
   167  						},
   168  					}}, ctx.Err()
   169  				}
   170  			})
   171  
   172  			It("ignores them", func() {
   173  				Eventually(readStart).Should(Receive(BeTemporally("~", time.Now().Add(-5*time.Second), time.Second)))
   174  			})
   175  		})
   176  
   177  		When("cancelling log streaming", func() {
   178  			BeforeEach(func() {
   179  				fakeLogCacheClient.ReadStub = func(
   180  					ctx context.Context,
   181  					sourceID string,
   182  					start time.Time,
   183  					opts ...logcache.ReadOption,
   184  				) ([]*loggregator_v2.Envelope, error) {
   185  					return nil, ctx.Err()
   186  				}
   187  			})
   188  
   189  			It("can be called multiple times", func() {
   190  				Expect(stopStreaming).ToNot(Panic())
   191  				Expect(stopStreaming).ToNot(Panic())
   192  			})
   193  		})
   194  
   195  		Describe("log cache error", func() {
   196  			BeforeEach(func() {
   197  				fakeLogCacheClient.ReadStub = func(
   198  					ctx context.Context,
   199  					sourceID string,
   200  					start time.Time,
   201  					opts ...logcache.ReadOption,
   202  				) ([]*loggregator_v2.Envelope, error) {
   203  					if fakeLogCacheClient.ReadCallCount() > 2 {
   204  						stopStreaming()
   205  					}
   206  
   207  					return nil, fmt.Errorf("error number %d", fakeLogCacheClient.ReadCallCount())
   208  				}
   209  			})
   210  
   211  			It("passes them through the errors channel", func() {
   212  				Eventually(errs).Should(HaveLen(2))
   213  				Eventually(errs).Should(Receive(MatchError("error number 1")))
   214  				Eventually(errs).Should(Receive(MatchError("error number 2")))
   215  			})
   216  		})
   217  	})
   218  
   219  	Describe("GetRecentLogs", func() {
   220  		When("the application can be found", func() {
   221  			When("Log Cache returns logs", func() {
   222  				BeforeEach(func() {
   223  					messages := []*loggregator_v2.Envelope{
   224  						{
   225  							Timestamp:  int64(20),
   226  							SourceId:   "some-app-guid",
   227  							InstanceId: "some-source-instance",
   228  							Message: &loggregator_v2.Envelope_Log{
   229  								Log: &loggregator_v2.Log{
   230  									Payload: []byte("message-2"),
   231  									Type:    loggregator_v2.Log_OUT,
   232  								},
   233  							},
   234  							Tags: map[string]string{
   235  								"source_type": "some-source-type",
   236  							},
   237  						},
   238  						{
   239  							Timestamp:  int64(10),
   240  							SourceId:   "some-app-guid",
   241  							InstanceId: "some-source-instance",
   242  							Message: &loggregator_v2.Envelope_Log{
   243  								Log: &loggregator_v2.Log{
   244  									Payload: []byte("message-1"),
   245  									Type:    loggregator_v2.Log_OUT,
   246  								},
   247  							},
   248  							Tags: map[string]string{
   249  								"source_type": "some-source-type",
   250  							},
   251  						},
   252  					}
   253  
   254  					fakeLogCacheClient.ReadReturns(messages, nil)
   255  				})
   256  
   257  				It("returns all the recent logs and warnings", func() {
   258  					messages, err := loggingaction.GetRecentLogs("some-app-guid", fakeLogCacheClient)
   259  					Expect(err).ToNot(HaveOccurred())
   260  
   261  					Expect(messages[0].Message).To(Equal("message-1"))
   262  					Expect(messages[0].MessageType).To(Equal("OUT"))
   263  					Expect(messages[0].Timestamp).To(Equal(time.Unix(0, 10)))
   264  					Expect(messages[0].SourceType).To(Equal("some-source-type"))
   265  					Expect(messages[0].SourceInstance).To(Equal("some-source-instance"))
   266  
   267  					Expect(messages[1].Message).To(Equal("message-2"))
   268  					Expect(messages[1].MessageType).To(Equal("OUT"))
   269  					Expect(messages[1].Timestamp).To(Equal(time.Unix(0, 20)))
   270  					Expect(messages[1].SourceType).To(Equal("some-source-type"))
   271  					Expect(messages[1].SourceInstance).To(Equal("some-source-instance"))
   272  				})
   273  			})
   274  
   275  			When("Log Cache returns non-log envelopes", func() {
   276  				BeforeEach(func() {
   277  					messages := []*loggregator_v2.Envelope{
   278  						{
   279  							Timestamp:  int64(10),
   280  							SourceId:   "some-app-guid",
   281  							InstanceId: "some-source-instance",
   282  							Message:    &loggregator_v2.Envelope_Counter{},
   283  							Tags: map[string]string{
   284  								"source_type": "some-source-type",
   285  							},
   286  						},
   287  					}
   288  
   289  					fakeLogCacheClient.ReadReturns(messages, nil)
   290  				})
   291  
   292  				It("ignores them", func() {
   293  					messages, err := loggingaction.GetRecentLogs("some-app-guid", fakeLogCacheClient)
   294  					Expect(err).ToNot(HaveOccurred())
   295  					Expect(messages).To(BeEmpty())
   296  				})
   297  			})
   298  
   299  			When("Log Cache errors", func() {
   300  				var expectedErr error
   301  
   302  				BeforeEach(func() {
   303  					expectedErr = errors.New("ZOMG")
   304  					fakeLogCacheClient.ReadReturns(nil, expectedErr)
   305  				})
   306  
   307  				It("returns error and warnings", func() {
   308  					_, err := loggingaction.GetRecentLogs("some-app-guid", fakeLogCacheClient)
   309  					Expect(err).To(MatchError(expectedErr))
   310  				})
   311  			})
   312  		})
   313  	})
   314  })