github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/cf/api/logs/log_cache_repository_test.go (about)

     1  package logs_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/actor/sharedaction"
     9  	"code.cloudfoundry.org/cli/actor/sharedaction/sharedactionfakes"
    10  	"code.cloudfoundry.org/cli/cf/api/logs"
    11  	. "github.com/onsi/ginkgo"
    12  	. "github.com/onsi/gomega"
    13  )
    14  
    15  var _ = Describe("logs with log cache", func() {
    16  
    17  	Describe("RecentLogsFor", func() {
    18  		It("retrieves the logs", func() {
    19  			recentLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, error) {
    20  				message := *sharedaction.NewLogMessage(
    21  					"some-message",
    22  					"OUT",
    23  					time.Unix(0, 0),
    24  					"STG",
    25  					"some-source-instance",
    26  				)
    27  				message2 := *sharedaction.NewLogMessage(
    28  					"some-message2",
    29  					"OUT",
    30  					time.Unix(0, 0),
    31  					"STG",
    32  					"some-source-instance2",
    33  				)
    34  				return []sharedaction.LogMessage{message, message2}, nil
    35  			}
    36  			getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) {
    37  				inputLogChan := make(chan sharedaction.LogMessage)
    38  				errors := make(chan error)
    39  				cancelFunc := func() {}
    40  				return inputLogChan, errors, cancelFunc
    41  			}
    42  			client := sharedactionfakes.FakeLogCacheClient{}
    43  			repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc)
    44  			logs, err := repository.RecentLogsFor("app-guid")
    45  
    46  			Expect(err).ToNot(HaveOccurred())
    47  			Expect(len(logs)).To(Equal(2))
    48  			Expect(logs[0].ToSimpleLog()).To(Equal("some-message"))
    49  			Expect(logs[1].ToSimpleLog()).To(Equal("some-message2"))
    50  		})
    51  
    52  		When("theres an error retrieving the logs", func() {
    53  			It("returns the error", func() {
    54  				recentLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, error) {
    55  					return nil, errors.New("some error")
    56  				}
    57  				getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) {
    58  					inputLogChan := make(chan sharedaction.LogMessage)
    59  					errors := make(chan error)
    60  					cancelFunc := func() {}
    61  					return inputLogChan, errors, cancelFunc
    62  				}
    63  				client := sharedactionfakes.FakeLogCacheClient{}
    64  				repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc)
    65  				_, err := repository.RecentLogsFor("app-guid")
    66  				Expect(err).To(MatchError("some error"))
    67  			})
    68  		})
    69  	})
    70  
    71  	Describe("TailLogsFor", func() {
    72  		var (
    73  			inputLogChan    chan sharedaction.LogMessage
    74  			inputErrorChan  chan error
    75  			logCacheMessage *logs.LogCacheMessage
    76  			internalError   error
    77  		)
    78  
    79  		cancelFunc := func() {}
    80  
    81  		recentLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, error) {
    82  			return []sharedaction.LogMessage{}, nil
    83  		}
    84  
    85  		It("writes to output log channel until input log message channel is closed", func() {
    86  			getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) {
    87  				inputLogChan = make(chan sharedaction.LogMessage, 2)
    88  				inputErrorChan = make(chan error, 2)
    89  
    90  				go func() {
    91  					defer close(inputLogChan)
    92  
    93  					message := *sharedaction.NewLogMessage(
    94  						"some-message",
    95  						"OUT",
    96  						time.Unix(0, 0),
    97  						"STG",
    98  						"some-source-instance",
    99  					)
   100  					message2 := *sharedaction.NewLogMessage(
   101  						"some-message2",
   102  						"OUT",
   103  						time.Unix(0, 0),
   104  						"STG",
   105  						"some-source-instance2",
   106  					)
   107  					inputLogChan <- message
   108  					inputLogChan <- message2
   109  
   110  					time.Sleep(1 * time.Second)
   111  				}()
   112  
   113  				return inputLogChan, inputErrorChan, cancelFunc
   114  			}
   115  
   116  			client := sharedactionfakes.FakeLogCacheClient{}
   117  			repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc)
   118  			outputLogChan := make(chan logs.Loggable, 2)
   119  			outputErrorChan := make(chan error, 2)
   120  
   121  			repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan)
   122  
   123  			Eventually(outputLogChan).Should(HaveLen(2))
   124  			Expect(outputLogChan).To(Receive(&logCacheMessage))
   125  			Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message"))
   126  			Expect(outputLogChan).To(Receive(&logCacheMessage))
   127  			Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message2"))
   128  			Expect(inputErrorChan).ToNot(Receive())
   129  		})
   130  
   131  		It("writes to output log channel until input error channel is closed", func() {
   132  			getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) {
   133  				inputLogChan = make(chan sharedaction.LogMessage, 2)
   134  				inputErrorChan = make(chan error, 2)
   135  
   136  				go func() {
   137  					defer close(inputErrorChan)
   138  
   139  					message := *sharedaction.NewLogMessage(
   140  						"some-message",
   141  						"OUT",
   142  						time.Unix(0, 0),
   143  						"STG",
   144  						"some-source-instance",
   145  					)
   146  					message2 := *sharedaction.NewLogMessage(
   147  						"some-message2",
   148  						"OUT",
   149  						time.Unix(0, 0),
   150  						"STG",
   151  						"some-source-instance2",
   152  					)
   153  					inputLogChan <- message
   154  					inputLogChan <- message2
   155  
   156  					time.Sleep(1 * time.Second)
   157  				}()
   158  
   159  				return inputLogChan, inputErrorChan, cancelFunc
   160  			}
   161  
   162  			client := sharedactionfakes.FakeLogCacheClient{}
   163  			repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc)
   164  			outputLogChan := make(chan logs.Loggable, 2)
   165  			outputErrorChan := make(chan error, 2)
   166  
   167  			repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan)
   168  
   169  			Eventually(outputLogChan).Should(HaveLen(2))
   170  			Expect(outputLogChan).To(Receive(&logCacheMessage))
   171  			Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message"))
   172  			Expect(outputLogChan).To(Receive(&logCacheMessage))
   173  			Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message2"))
   174  			Expect(inputErrorChan).ToNot(Receive())
   175  		})
   176  
   177  		It("writes recoverable errors to output error channel until input error channel is closed", func() {
   178  			getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) {
   179  				inputLogChan = make(chan sharedaction.LogMessage)
   180  				inputErrorChan = make(chan error, 1)
   181  
   182  				go func() {
   183  					defer close(inputErrorChan)
   184  					inputErrorChan <- errors.New("internal error")
   185  					time.Sleep(1 * time.Second)
   186  				}()
   187  
   188  				return inputLogChan, inputErrorChan, cancelFunc
   189  			}
   190  
   191  			client := sharedactionfakes.FakeLogCacheClient{}
   192  			repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc)
   193  			outputLogChan := make(chan logs.Loggable)
   194  			outputErrorChan := make(chan error, 1)
   195  			repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan)
   196  
   197  			Eventually(outputErrorChan).Should(HaveLen(1))
   198  			Expect(outputErrorChan).To(Receive(&internalError))
   199  			Expect(internalError).To(MatchError("internal error"))
   200  			Expect(inputLogChan).ToNot(Receive())
   201  		})
   202  
   203  		It("writes recoverable errors to output error channel until input log message channel is closed", func() {
   204  			getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) {
   205  				inputLogChan = make(chan sharedaction.LogMessage)
   206  				inputErrorChan = make(chan error, 1)
   207  
   208  				go func() {
   209  					defer close(inputLogChan)
   210  					inputErrorChan <- errors.New("internal error")
   211  					time.Sleep(1 * time.Second)
   212  				}()
   213  
   214  				return inputLogChan, inputErrorChan, cancelFunc
   215  			}
   216  
   217  			client := sharedactionfakes.FakeLogCacheClient{}
   218  			repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc)
   219  			outputLogChan := make(chan logs.Loggable)
   220  			outputErrorChan := make(chan error, 1)
   221  			repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan)
   222  
   223  			Eventually(outputErrorChan).Should(HaveLen(1))
   224  			Expect(outputErrorChan).To(Receive(&internalError))
   225  			Expect(internalError).To(MatchError("internal error"))
   226  			Expect(inputLogChan).ToNot(Receive())
   227  		})
   228  
   229  		When("Close() called", func() {
   230  
   231  			It("calls repository.cancelFunc", func() {
   232  				cancelFuncCallCount := 0
   233  
   234  				cancelFunc = func() {
   235  					cancelFuncCallCount += 1
   236  				}
   237  
   238  				getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) {
   239  					inputLogChan = make(chan sharedaction.LogMessage)
   240  					inputErrorChan = make(chan error, 1)
   241  					close(inputLogChan)
   242  					close(inputErrorChan)
   243  					return inputLogChan, inputErrorChan, cancelFunc
   244  				}
   245  
   246  				client := sharedactionfakes.FakeLogCacheClient{}
   247  				repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc)
   248  				outputLogChan := make(chan logs.Loggable)
   249  				outputErrorChan := make(chan error, 1)
   250  
   251  				repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan)
   252  				repository.Close()
   253  				Expect(cancelFuncCallCount).To(Equal(1))
   254  			})
   255  		})
   256  	})
   257  
   258  	XDescribe("Authentication Token Refresh", func() {
   259  	})
   260  })