github.com/argoproj/argo-events@v1.9.1/eventsources/common/naivewatcher/watcher_test.go (about)

     1  package naivewatcher
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"syscall"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/argoproj/argo-events/eventsources/common/fsevent"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  type WatchableTestFS struct {
    16  }
    17  
    18  type TestFSID struct {
    19  	Device int32
    20  	Inode  uint64
    21  }
    22  
    23  func (w *WatchableTestFS) Walk(root string, walkFn filepath.WalkFunc) error {
    24  	return filepath.Walk(root, walkFn)
    25  }
    26  
    27  func (w *WatchableTestFS) GetFileID(fi os.FileInfo) interface{} {
    28  	stat := fi.Sys().(*syscall.Stat_t)
    29  	return TestFSID{
    30  		Device: int32(stat.Dev),
    31  		Inode:  stat.Ino,
    32  	}
    33  }
    34  
    35  func TestWatcherAutoCheck(t *testing.T) {
    36  	watcher, err := NewWatcher(&WatchableTestFS{})
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	defer watcher.Close()
    41  
    42  	tmpdir, err := os.MkdirTemp("", "naive-watcher-")
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	defer os.RemoveAll(tmpdir)
    47  
    48  	err = watcher.Add(tmpdir)
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	err = watcher.Start(50 * time.Millisecond)
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  	defer func() {
    58  		if err := watcher.Stop(); err != nil {
    59  			fmt.Printf("failed to stop the watcher. err: %+v\n", err)
    60  		}
    61  	}()
    62  
    63  	// Create a file
    64  	_, err = os.Create(filepath.Join(tmpdir, "foo"))
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	time.Sleep(300 * time.Millisecond)
    69  	events := readEvents(t, watcher)
    70  	assert.Equal(t, []fsevent.Event{
    71  		{Op: fsevent.Create, Name: filepath.Join(tmpdir, "foo")},
    72  	}, events)
    73  
    74  	// Rename a file
    75  	err = os.Rename(filepath.Join(tmpdir, "foo"), filepath.Join(tmpdir, "bar"))
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	time.Sleep(300 * time.Millisecond)
    80  	events = readEvents(t, watcher)
    81  	assert.Equal(t, []fsevent.Event{
    82  		{Op: fsevent.Rename, Name: filepath.Join(tmpdir, "bar")},
    83  	}, events)
    84  
    85  	// Write a file
    86  	err = os.WriteFile(filepath.Join(tmpdir, "bar"), []byte("wow"), 0666)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  	time.Sleep(300 * time.Millisecond)
    91  	events = readEvents(t, watcher)
    92  	assert.Equal(t, []fsevent.Event{
    93  		{Op: fsevent.Write, Name: filepath.Join(tmpdir, "bar")},
    94  	}, events)
    95  
    96  	// Chmod a file
    97  	err = os.Chmod(filepath.Join(tmpdir, "bar"), 0777)
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	time.Sleep(300 * time.Millisecond)
   102  	events = readEvents(t, watcher)
   103  	assert.Equal(t, []fsevent.Event{
   104  		{Op: fsevent.Chmod, Name: filepath.Join(tmpdir, "bar")},
   105  	}, events)
   106  
   107  	// Rename & Write & Chmod a file
   108  	err = os.Rename(filepath.Join(tmpdir, "bar"), filepath.Join(tmpdir, "foo"))
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  	err = os.WriteFile(filepath.Join(tmpdir, "foo"), []byte("wowwow"), 0666)
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	err = os.Chmod(filepath.Join(tmpdir, "foo"), 0770)
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	var actualOps fsevent.Op
   121  	time.Sleep(300 * time.Millisecond)
   122  	events = readEvents(t, watcher)
   123  	for _, event := range events {
   124  		if event.Name == filepath.Join(tmpdir, "foo") {
   125  			actualOps |= event.Op
   126  		}
   127  	}
   128  	assert.Equal(t, fsevent.Write|fsevent.Rename|fsevent.Chmod, actualOps)
   129  
   130  	// Remove a file
   131  	err = os.Remove(filepath.Join(tmpdir, "foo"))
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  	time.Sleep(300 * time.Millisecond)
   136  	events = readEvents(t, watcher)
   137  	assert.Equal(t, []fsevent.Event{
   138  		{Op: fsevent.Remove, Name: filepath.Join(tmpdir, "foo")},
   139  	}, events)
   140  
   141  	err = watcher.Stop()
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  
   146  	err = watcher.Remove(tmpdir)
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  }
   151  
   152  func TestWatcherManualCheck(t *testing.T) {
   153  	watcher, err := NewWatcher(&WatchableTestFS{})
   154  	if err != nil {
   155  		t.Fatal(err)
   156  	}
   157  	defer watcher.Close()
   158  
   159  	tmpdir, err := os.MkdirTemp("", "naive-watcher-")
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	defer os.RemoveAll(tmpdir)
   164  
   165  	err = watcher.Add(tmpdir)
   166  	if err != nil {
   167  		t.Fatal(err)
   168  	}
   169  
   170  	events := checkAndReadEvents(t, watcher)
   171  	assert.Equal(t, []fsevent.Event{}, events)
   172  
   173  	// Create a file
   174  	_, err = os.Create(filepath.Join(tmpdir, "foo"))
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	events = checkAndReadEvents(t, watcher)
   179  	assert.Equal(t, []fsevent.Event{
   180  		{Op: fsevent.Create, Name: filepath.Join(tmpdir, "foo")},
   181  	}, events)
   182  
   183  	// Rename a file
   184  	err = os.Rename(filepath.Join(tmpdir, "foo"), filepath.Join(tmpdir, "bar"))
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  	events = checkAndReadEvents(t, watcher)
   189  	assert.Equal(t, []fsevent.Event{
   190  		{Op: fsevent.Rename, Name: filepath.Join(tmpdir, "bar")},
   191  	}, events)
   192  
   193  	// Write a file
   194  	err = os.WriteFile(filepath.Join(tmpdir, "bar"), []byte("wow"), 0666)
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	events = checkAndReadEvents(t, watcher)
   199  	assert.Equal(t, []fsevent.Event{
   200  		{Op: fsevent.Write, Name: filepath.Join(tmpdir, "bar")},
   201  	}, events)
   202  
   203  	// Chmod a file
   204  	err = os.Chmod(filepath.Join(tmpdir, "bar"), 0777)
   205  	if err != nil {
   206  		t.Fatal(err)
   207  	}
   208  	events = checkAndReadEvents(t, watcher)
   209  	assert.Equal(t, []fsevent.Event{
   210  		{Op: fsevent.Chmod, Name: filepath.Join(tmpdir, "bar")},
   211  	}, events)
   212  
   213  	// Rename & Write & Chmod a file
   214  	err = os.Rename(filepath.Join(tmpdir, "bar"), filepath.Join(tmpdir, "foo"))
   215  	if err != nil {
   216  		t.Fatal(err)
   217  	}
   218  	err = os.WriteFile(filepath.Join(tmpdir, "foo"), []byte("wowwow"), 0666)
   219  	if err != nil {
   220  		t.Fatal(err)
   221  	}
   222  	err = os.Chmod(filepath.Join(tmpdir, "foo"), 0770)
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  	events = checkAndReadEvents(t, watcher)
   227  	assert.Equal(t, []fsevent.Event{
   228  		{Op: fsevent.Write | fsevent.Rename | fsevent.Chmod, Name: filepath.Join(tmpdir, "foo")},
   229  	}, events)
   230  
   231  	// Remove a file
   232  	err = os.Remove(filepath.Join(tmpdir, "foo"))
   233  	if err != nil {
   234  		t.Fatal(err)
   235  	}
   236  	events = checkAndReadEvents(t, watcher)
   237  	assert.Equal(t, []fsevent.Event{
   238  		{Op: fsevent.Remove, Name: filepath.Join(tmpdir, "foo")},
   239  	}, events)
   240  
   241  	err = watcher.Remove(tmpdir)
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  }
   246  
   247  func checkAndReadEvents(t *testing.T, watcher *Watcher) []fsevent.Event {
   248  	err := watcher.Check()
   249  	if err != nil {
   250  		t.Fatal(err)
   251  	}
   252  	return readEvents(t, watcher)
   253  }
   254  
   255  func readEvents(t *testing.T, watcher *Watcher) []fsevent.Event {
   256  	events := []fsevent.Event{}
   257  L:
   258  	for {
   259  		select {
   260  		case event := <-watcher.Events:
   261  			events = append(events, event)
   262  		default:
   263  			break L
   264  		}
   265  	}
   266  	return events
   267  }