istio
143 строки · 3.6 Кб
1// Copyright Istio Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package filewatcher16
17import (18"errors"19"fmt"20"sync"21
22"github.com/fsnotify/fsnotify"23)
24
25// NewFileWatcherFunc returns a function which creates a new file
26// watcher. This may be used to provide test hooks for using the
27// FakeWatcher implementation below.
28type NewFileWatcherFunc func() FileWatcher29
30// FakeWatcher provides a fake file watcher implementation for unit
31// tests. Production code should use the `NewWatcher()`.
32type FakeWatcher struct {33sync.Mutex34
35events map[string]chan fsnotify.Event36errors map[string]chan error37changedFunc func(path string, added bool)38}
39
40// InjectEvent injects an event into the fake file watcher.
41func (w *FakeWatcher) InjectEvent(path string, event fsnotify.Event) {42w.Lock()43ch, ok := w.events[path]44w.Unlock()45
46if ok {47ch <- event48}49}
50
51// InjectError injects an error into the fake file watcher.
52func (w *FakeWatcher) InjectError(path string, err error) {53w.Lock()54ch, ok := w.errors[path]55w.Unlock()56
57if ok {58ch <- err59}60}
61
62// NewFakeWatcher returns a function which creates a new fake watcher for unit
63// testing. This allows observe callers to inject events and errors per-watched
64// path. changedFunc() provides a callback notification when a new watch is added
65// or removed. Production code should use `NewWatcher()`.
66func NewFakeWatcher(changedFunc func(path string, added bool)) (NewFileWatcherFunc, *FakeWatcher) {67w := &FakeWatcher{68events: make(map[string]chan fsnotify.Event),69errors: make(map[string]chan error),70changedFunc: changedFunc,71}72return func() FileWatcher {73return w74}, w75}
76
77// Add is a fake implementation of the FileWatcher interface.
78func (w *FakeWatcher) Add(path string) error {79w.Lock()80
81// w.events and w.errors are always updated togeather. We only check82// the first to determine existence.83if _, ok := w.events[path]; ok {84w.Unlock()85return fmt.Errorf("path %v already exists", path)86}87
88w.events[path] = make(chan fsnotify.Event, 1000)89w.errors[path] = make(chan error, 1000)90
91w.Unlock()92
93if w.changedFunc != nil {94w.changedFunc(path, true)95}96return nil97}
98
99// Remove is a fake implementation of the FileWatcher interface.
100func (w *FakeWatcher) Remove(path string) error {101w.Lock()102defer w.Unlock()103
104if _, ok := w.events[path]; !ok {105return errors.New("path doesn't exist")106}107
108delete(w.events, path)109delete(w.errors, path)110if w.changedFunc != nil {111w.changedFunc(path, false)112}113return nil114}
115
116// Close is a fake implementation of the FileWatcher interface.
117func (w *FakeWatcher) Close() error {118w.Lock()119for path, ch := range w.events {120close(ch)121delete(w.events, path)122}123for path, ch := range w.errors {124close(ch)125delete(w.errors, path)126}127defer w.Unlock()128return nil129}
130
131// Events is a fake implementation of the FileWatcher interface.
132func (w *FakeWatcher) Events(path string) chan fsnotify.Event {133w.Lock()134defer w.Unlock()135return w.events[path]136}
137
138// Errors is a fake implementation of the FileWatcher interface.
139func (w *FakeWatcher) Errors(path string) chan error {140w.Lock()141defer w.Unlock()142return w.errors[path]143}
144