knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/test/upgrade/functions.go (about) 1 /* 2 Copyright 2020 The Knative Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package upgrade 18 19 import ( 20 "testing" 21 "time" 22 23 "go.uber.org/zap" 24 "go.uber.org/zap/zaptest" 25 ) 26 27 // Execute the Suite of upgrade tests with a Configuration given. 28 // When the suite includes Continual tests the number of logical CPUs 29 // usable by the test process must be at least <NUMBER OF CONTINUAL TESTS> + 1. 30 // The -parallel test flag or GOMAXPROCS environment variable might be 31 // used to adjust the settings. 32 func (s *Suite) Execute(c Configuration) { 33 l := c.logger(c.T) 34 se := suiteExecution{ 35 suite: enrichSuite(s), 36 configuration: c, 37 } 38 l.Info("🏃 Running upgrade test suite...") 39 40 se.execute() 41 42 if !c.T.Failed() { 43 l.Info("🥳🎉 Success! Upgrade suite completed without errors.") 44 } else { 45 l.Error("💣🤬💔️ Upgrade suite have failed!") 46 } 47 } 48 49 func (c Configuration) logger(t *testing.T) *zap.SugaredLogger { 50 return zaptest.NewLogger(t, zaptest.WrapOptions(c.Options...)).Sugar() 51 } 52 53 // NewOperation creates a new upgrade operation or test. 54 func NewOperation(name string, handler func(c Context)) Operation { 55 return &simpleOperation{name: name, handler: handler} 56 } 57 58 // NewBackgroundVerification is convenience function to easily setup a 59 // background operation that will setup environment and then verify environment 60 // status after receiving a stop event. 61 func NewBackgroundVerification(name string, setup func(c Context), verify func(c Context)) BackgroundOperation { 62 return NewBackgroundOperation(name, setup, func(bc BackgroundContext) { 63 WaitForStopEvent(bc, WaitForStopEventConfiguration{ 64 Name: name, 65 OnStop: func() { 66 verify(Context{ 67 T: bc.T, 68 Log: bc.Log, 69 }) 70 }, 71 OnWait: DefaultOnWait, 72 WaitTime: DefaultWaitTime, 73 }) 74 }) 75 } 76 77 // NewBackgroundOperation creates a new background operation or test that can be 78 // notified to stop its operation. 79 func NewBackgroundOperation(name string, setup func(c Context), 80 handler func(bc BackgroundContext), 81 ) BackgroundOperation { 82 return &simpleBackgroundOperation{ 83 name: name, 84 setup: setup, 85 handler: handler, 86 } 87 } 88 89 // WaitForStopEvent will wait until upgrade suite sends a stop event to it. 90 // After that happen a handler is invoked to verify environment state and report 91 // failures. 92 func WaitForStopEvent(bc BackgroundContext, w WaitForStopEventConfiguration) { 93 for { 94 select { 95 case <-bc.Stop: 96 bc.Log.Debugf("%s received a stop event", w.Name) 97 w.OnStop() 98 return 99 default: 100 w.OnWait(bc, w) 101 } 102 time.Sleep(w.WaitTime) 103 } 104 } 105 106 func enrichSuite(s *Suite) *enrichedSuite { 107 es := &enrichedSuite{ 108 installations: s.Installations, 109 tests: enrichedTests{ 110 preUpgrade: s.Tests.PreUpgrade, 111 postUpgrade: s.Tests.PostUpgrade, 112 postDowngrade: s.Tests.PostDowngrade, 113 continual: make([]stoppableOperation, len(s.Tests.Continual)), 114 }, 115 } 116 for i, test := range s.Tests.Continual { 117 es.tests.continual[i] = stoppableOperation{ 118 BackgroundOperation: test, 119 stop: make(chan struct{}), 120 } 121 } 122 return es 123 } 124 125 // Name is a human readable operation title, and it will be used in t.Run. 126 func (h *simpleOperation) Name() string { 127 return h.name 128 } 129 130 // Handler is a function that will be called to perform an operation. 131 func (h *simpleOperation) Handler() func(c Context) { 132 return h.handler 133 } 134 135 // Name is a human readable operation title, and it will be used in t.Run. 136 func (s *simpleBackgroundOperation) Name() string { 137 return s.name 138 } 139 140 // Setup method may be used to set up environment before upgrade/downgrade is 141 // performed. 142 func (s *simpleBackgroundOperation) Setup() func(c Context) { 143 return s.setup 144 } 145 146 // Handler will be executed in background while upgrade/downgrade is being 147 // executed. It can be used to constantly validate environment during that 148 // time and/or wait for a stop event being sent. After a stop event is received 149 // user should validate environment, clean up resources, and report found 150 // issues to testing.T forwarded in BackgroundContext. 151 func (s *simpleBackgroundOperation) Handler() func(bc BackgroundContext) { 152 return s.handler 153 }