github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/container/kvm/mock/mock-kvm.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package mock 5 6 import ( 7 "fmt" 8 "sync" 9 10 "github.com/juju/juju/container/kvm" 11 ) 12 13 // This file provides a mock implementation of the kvm interfaces 14 // ContainerFactory and Container. 15 16 type Action int 17 18 const ( 19 // A container has been started. 20 Started Action = iota 21 // A container has been stopped. 22 Stopped 23 ) 24 25 func (action Action) String() string { 26 switch action { 27 case Started: 28 return "Started" 29 case Stopped: 30 return "Stopped" 31 } 32 return "unknown" 33 } 34 35 type Event struct { 36 Action Action 37 InstanceId string 38 } 39 40 type ContainerFactory interface { 41 kvm.ContainerFactory 42 43 AddListener(chan<- Event) 44 RemoveListener(chan<- Event) 45 HasListener(chan<- Event) bool 46 } 47 48 type mockFactory struct { 49 instances map[string]kvm.Container 50 listeners []chan<- Event 51 mu sync.Mutex 52 } 53 54 func MockFactory() ContainerFactory { 55 return &mockFactory{ 56 instances: make(map[string]kvm.Container), 57 } 58 } 59 60 type MockContainer struct { 61 StartParams kvm.StartParams 62 63 factory *mockFactory 64 name string 65 started bool 66 } 67 68 // Name returns the name of the container. 69 func (mock *MockContainer) Name() string { 70 return mock.name 71 } 72 73 // imageCacheCalls does nothing more than get incremented by calls to the 74 // mocked EnsureCachedImage method below. 75 // However, it will cause the race checker to fail if such calls are not made 76 // in a Goroutine safe manner. 77 var imageCacheCalls int //nolint:unused 78 79 // EnsureCachedImage is the first supply of start-params to the container. 80 // We set it here for subsequent test assertions. 81 // Start is called by the manager immediately after, with the same argument. 82 func (mock *MockContainer) EnsureCachedImage(params kvm.StartParams) error { 83 imageCacheCalls++ 84 mock.StartParams = params 85 return nil 86 } 87 88 func (mock *MockContainer) Start(params kvm.StartParams) error { 89 if mock.started { 90 return fmt.Errorf("container is already running") 91 } 92 mock.started = true 93 mock.factory.notify(Started, mock.name) 94 return nil 95 } 96 97 // Stop terminates the running container. 98 func (mock *MockContainer) Stop() error { 99 if !mock.started { 100 return fmt.Errorf("container is not running") 101 } 102 mock.started = false 103 mock.factory.notify(Stopped, mock.name) 104 return nil 105 } 106 107 func (mock *MockContainer) IsRunning() bool { 108 return mock.started 109 } 110 111 // String returns information about the container. 112 func (mock *MockContainer) String() string { 113 return fmt.Sprintf("<MockContainer %q>", mock.name) 114 } 115 116 func (mock *mockFactory) String() string { 117 return fmt.Sprintf("<Mock KVM Factory>") 118 } 119 120 func (mock *mockFactory) New(name string) kvm.Container { 121 mock.mu.Lock() 122 defer mock.mu.Unlock() 123 124 container, ok := mock.instances[name] 125 if ok { 126 return container 127 } 128 container = &MockContainer{ 129 factory: mock, 130 name: name, 131 } 132 mock.instances[name] = container 133 return container 134 } 135 136 func (mock *mockFactory) List() (result []kvm.Container, err error) { 137 for _, container := range mock.instances { 138 result = append(result, container) 139 } 140 return 141 } 142 143 func (mock *mockFactory) notify(action Action, instanceId string) { 144 event := Event{action, instanceId} 145 for _, c := range mock.listeners { 146 c <- event 147 } 148 } 149 150 func (mock *mockFactory) AddListener(listener chan<- Event) { 151 mock.listeners = append(mock.listeners, listener) 152 } 153 154 func (mock *mockFactory) RemoveListener(listener chan<- Event) { 155 pos := 0 156 for i, c := range mock.listeners { 157 if c == listener { 158 pos = i 159 } 160 } 161 mock.listeners = append(mock.listeners[:pos], mock.listeners[pos+1:]...) 162 } 163 164 func (mock *mockFactory) HasListener(listener chan<- Event) bool { 165 for _, c := range mock.listeners { 166 if c == listener { 167 return true 168 } 169 } 170 return false 171 }