Skip to content

Commit

Permalink
fix: copy correct node if parent watchpoint changes
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianKramm committed Jul 19, 2021
1 parent de179dd commit c45ceae
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 13 deletions.
69 changes: 57 additions & 12 deletions notify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,27 @@ func TestRenameInRoot(t *testing.T) {
}
}

func prepareTestDir(t *testing.T) string {
tmpDir, err := ioutil.TempDir("", "notify_test-")
if err != nil {
t.Fatal(err)
}

// resolve paths on OSX
s, err := filepath.EvalSymlinks(tmpDir)
if err != nil {
t.Fatal(err)
}

// create test dir
err = os.MkdirAll(filepath.Join(s, "a/b/c"), 0755)
if err != nil {
t.Fatal(err)
}

return s
}

func mustWatch(t *testing.T, path string) chan EventInfo {
c := make(chan EventInfo, 1)
err := Watch(path+"...", c, All)
Expand All @@ -157,18 +178,43 @@ func mustWatch(t *testing.T, path string) chan EventInfo {
return c
}

func TestStopChild(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notify_test-")
if err != nil {
t.Fatal(err)
}
func TestAddParentAfterStop(t *testing.T) {
tmpDir := prepareTestDir(t)
defer os.RemoveAll(tmpDir)

// create test dir
err = os.MkdirAll(filepath.Join(tmpDir, "a/b/c"), 0755)
if err != nil {
t.Fatal(err)
// watch a child and parent path across multiple channels.
// this can happen in any order.
ch1 := mustWatch(t, filepath.Join(tmpDir, "a/b"))
ch2 := mustWatch(t, filepath.Join(tmpDir, "a/b/c"))

// unwatch ./a/b -- this is what causes the panic on the next line.
// note that this also fails if we notify.Stop(ch1) instead.
Stop(ch1)

// add parent watchpoint
_ = mustWatch(t, filepath.Join(tmpDir, "a"))

// fire an event
filePath := filepath.Join(tmpDir, "a/b/c/d")
go func() { _ = ioutil.WriteFile(filePath, []byte("X"), 0664) }()

timeout := time.After(5 * time.Second)
for {
select {
case ev := <-ch2:
t.Log(ev.Path(), ev.Event())
if ev.Path() == filePath && ev.Event() == Write {
return
}
case <-timeout:
t.Fatal("timed out before receiving event")
}
}
}

func TestStopChild(t *testing.T) {
tmpDir := prepareTestDir(t)
defer os.RemoveAll(tmpDir)

// watch a child and parent path across multiple channels.
// this can happen in any order.
Expand All @@ -178,16 +224,15 @@ func TestStopChild(t *testing.T) {
// this leads to tmpDir/a being unwatched
Stop(ch2)

// fire an event that will never show up because the watchpoint for ./a is removed
// as well.
// fire an event
filePath := filepath.Join(tmpDir, "a/b/c/d")
go func() { _ = ioutil.WriteFile(filePath, []byte("X"), 0664) }()

timeout := time.After(5 * time.Second)
for {
select {
case ev := <-ch1:
t.Log(filePath, ev.Path(), ev.Event())
t.Log(ev.Path(), ev.Event())
if ev.Path() == filePath && ev.Event() == Write {
return
}
Expand Down
6 changes: 5 additions & 1 deletion tree_recursive.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func watchCopy(src, dst node) {
}
if wpsrc := src.Child[""].Watch; len(wpsrc) != 0 {
wpdst := dst.Child[""].Watch
if wpdst == nil {
wpdst = make(watchpoint)
dst.Child[""] = node{Watch: wpdst}
}
for c, e := range wpsrc {
if c == nil {
continue
Expand Down Expand Up @@ -226,7 +230,7 @@ func (t *recursiveTree) Watch(path string, c chan<- EventInfo, events ...Event)
// Look for children nodes, unwatch n-1 of them and rewatch the last one.
var children []node
fn := func(nd node) error {
if len(nd.Watch) == 0 {
if watchTotal(nd) == 0 {
return nil
}
children = append(children, nd)
Expand Down

0 comments on commit c45ceae

Please sign in to comment.