From 456bbd1166fd87984d98fbc6029b5ce9798e451b Mon Sep 17 00:00:00 2001 From: Shulhan Date: Sun, 6 Mar 2022 17:58:58 +0700 Subject: lib/memfs: move the test for NewWatcher and DirWatcher as example With this we do one thing (write testing) and output two things (testing the code and give an example for code). --- lib/memfs/dirwatcher_example_test.go | 168 +++++++++++++++++++++++++++++ lib/memfs/dirwatcher_test.go | 199 +---------------------------------- lib/memfs/watcher_example_test.go | 82 +++++++++++++++ lib/memfs/watcher_test.go | 91 ---------------- 4 files changed, 253 insertions(+), 287 deletions(-) create mode 100644 lib/memfs/dirwatcher_example_test.go create mode 100644 lib/memfs/watcher_example_test.go delete mode 100644 lib/memfs/watcher_test.go diff --git a/lib/memfs/dirwatcher_example_test.go b/lib/memfs/dirwatcher_example_test.go new file mode 100644 index 00000000..a8468d80 --- /dev/null +++ b/lib/memfs/dirwatcher_example_test.go @@ -0,0 +1,168 @@ +// Copyright 2022, Shulhan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package memfs + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "time" +) + +func ExampleDirWatcher() { + var ( + ns NodeState + rootDir string + err error + ) + + rootDir, err = ioutil.TempDir("", "libmemfs") + if err != nil { + log.Fatal(err) + } + + // In this example, we watch sub directory "assets" and its contents, + // include only file with .adoc extension and ignoring files with + // .html extension. + dw := &DirWatcher{ + Options: Options{ + Root: rootDir, + Includes: []string{ + `assets/.*`, + `.*\.adoc$`, + }, + Excludes: []string{ + `.*\.html$`, + }, + }, + Delay: 150 * time.Millisecond, + } + + err = dw.Start() + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Deleting the root directory:\n") + err = os.Remove(rootDir) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s\n", ns.State, ns.Node.Path) + + // Create the root directory back with sub directory + // This will trigger two FileStateCreated events, one for "/" and one + // for "/assets". + dirAssets := filepath.Join(rootDir, "assets") + fmt.Printf("Re-create root directory with sub-directory:\n") + err = os.MkdirAll(dirAssets, 0770) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s\n", ns.State, ns.Node.Path) + ns = <-dw.C + fmt.Printf("-- %s %s\n", ns.State, ns.Node.Path) + + // Modify the permission on root directory + fmt.Printf("Chmod on root directory:\n") + err = os.Chmod(rootDir, 0700) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s %s\n", ns.State, ns.Node.Path, ns.Node.Mode()) + + newFile := filepath.Join(rootDir, "new.adoc") + fmt.Println("Create new file on root directory: /new.adoc") + err = ioutil.WriteFile(newFile, nil, 0600) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s %s\n", ns.State, ns.Node.Path, ns.Node.Mode()) + + fmt.Println("Remove file on root directory: /new.adoc") + err = os.Remove(newFile) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s %s\n", ns.State, ns.Node.Path, ns.Node.Mode()) + + // Create sub-directory. + subDir := filepath.Join(rootDir, "subdir") + fmt.Println("Create new sub-directory: /subdir") + err = os.Mkdir(subDir, 0770) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s %s\n", ns.State, ns.Node.Path, ns.Node.Mode()) + + // Add new file in sub directory. + newFile = filepath.Join(subDir, "new.adoc") + fmt.Println("Create new file in sub directory: /subdir/new.adoc") + err = ioutil.WriteFile(newFile, nil, 0600) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s %s\n", ns.State, ns.Node.Path, ns.Node.Mode()) + + fmt.Println("Remove file in sub directory: /subdir/new.adoc") + err = os.Remove(newFile) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s %s\n", ns.State, ns.Node.Path, ns.Node.Mode()) + + // Creating file that is excluded should not trigger event. + newFile = filepath.Join(subDir, "new.html") + fmt.Println("Create excluded file in sub directory: /subdir/new.html") + err = ioutil.WriteFile(newFile, nil, 0600) + if err != nil { + log.Fatal(err) + } + + // Create file without extension in directory "assets" should trigger + // event. + newFile = filepath.Join(dirAssets, "new") + fmt.Println("Create new file under assets: /assets/new") + err = ioutil.WriteFile(newFile, nil, 0600) + if err != nil { + log.Fatal(err) + } + ns = <-dw.C + fmt.Printf("-- %s %s %s\n", ns.State, ns.Node.Path, ns.Node.Mode()) + + dw.Stop() + + //Output: + //Deleting the root directory: + //-- FileStateDeleted / + //Re-create root directory with sub-directory: + //-- FileStateCreated / + //-- FileStateCreated /assets + //Chmod on root directory: + //-- FileStateUpdateMode / drwx------ + //Create new file on root directory: /new.adoc + //-- FileStateCreated /new.adoc -rw------- + //Remove file on root directory: /new.adoc + //-- FileStateDeleted /new.adoc -rw------- + //Create new sub-directory: /subdir + //-- FileStateCreated /subdir drwxr-x--- + //Create new file in sub directory: /subdir/new.adoc + //-- FileStateCreated /subdir/new.adoc -rw------- + //Remove file in sub directory: /subdir/new.adoc + //-- FileStateDeleted /subdir/new.adoc -rw------- + //Create excluded file in sub directory: /subdir/new.html + //Create new file under assets: /assets/new + //-- FileStateCreated /assets/new -rw------- +} diff --git a/lib/memfs/dirwatcher_test.go b/lib/memfs/dirwatcher_test.go index 4bf1cd48..a62f6001 100644 --- a/lib/memfs/dirwatcher_test.go +++ b/lib/memfs/dirwatcher_test.go @@ -5,8 +5,6 @@ package memfs import ( - "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -15,200 +13,6 @@ import ( "github.com/shuLhan/share/lib/test" ) -func TestDirWatcher(t *testing.T) { - var ( - err error - gotNS NodeState - dir string - x int - ) - - dir = t.TempDir() - if err != nil { - t.Fatal(err) - } - - fmt.Printf(">>> Watching directory %q for changes ...\n", dir) - - exps := []struct { - path string - state FileState - }{{ - state: FileStateDeleted, - path: "/", - }, { - state: FileStateCreated, - path: "/", - }, { - state: FileStateCreated, - path: "/assets", - }, { - state: FileStateUpdateMode, - path: "/", - }, { - state: FileStateCreated, - path: "/new.adoc", - }, { - state: FileStateDeleted, - path: "/new.adoc", - }, { - state: FileStateCreated, - path: "/sub", - }, { - state: FileStateCreated, - path: "/sub/new.adoc", - }, { - state: FileStateDeleted, - path: "/sub/new.adoc", - }, { - state: FileStateCreated, - path: "/assets/new", - }, { - state: FileStateDeleted, - path: "/assets/new", - }} - - dw := &DirWatcher{ - Options: Options{ - Root: dir, - Includes: []string{ - `assets/.*`, - `.*\.adoc$`, - }, - Excludes: []string{ - `.*\.html$`, - }, - }, - Delay: 150 * time.Millisecond, - } - - err = dw.Start() - if err != nil { - t.Fatal(err) - } - - // Delete the directory being watched. - t.Logf("Deleting root directory %q ...\n", dir) - err = os.Remove(dir) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Create the watched directory back with sub directory - // This will trigger two FileStateCreated events, one for "/" and one - // for "/assets". - dirAssets := filepath.Join(dir, "assets") - t.Logf("Re-create root directory %q ...\n", dirAssets) - err = os.MkdirAll(dirAssets, 0770) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Modify the permission on root directory - t.Logf("Modify root directory %q ...\n", dir) - err = os.Chmod(dir, 0700) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Add new file to watched directory. - newFile := filepath.Join(dir, "new.adoc") - t.Logf("Create new file on root directory: %q ...\n", newFile) - err = ioutil.WriteFile(newFile, nil, 0600) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Remove file. - t.Logf("Remove file on root directory: %q ...\n", newFile) - err = os.Remove(newFile) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Create sub-directory. - subDir := filepath.Join(dir, "sub") - t.Logf("Create new sub-directory: %q ...\n", subDir) - err = os.Mkdir(subDir, 0770) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Add new file in sub directory. - newFile = filepath.Join(subDir, "new.adoc") - t.Logf("Create new file in sub directory: %q ...\n", newFile) - err = ioutil.WriteFile(newFile, nil, 0600) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Remove file in sub directory. - t.Logf("Remove file in sub directory: %q ...\n", newFile) - err = os.Remove(newFile) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - // Create exclude file, should not trigger event. - newFile = filepath.Join(subDir, "new.html") - t.Logf("Create excluded file in sub directory: %q ...\n", newFile) - err = ioutil.WriteFile(newFile, nil, 0600) - if err != nil { - t.Fatal(err) - } - - // Create file without extension in white list directory "assets", - // should trigger event. - newFile = filepath.Join(dirAssets, "new") - t.Logf("Create new file on assets: %q ...\n", newFile) - err = ioutil.WriteFile(newFile, nil, 0600) - if err != nil { - t.Fatal(err) - } - gotNS = <-dw.C - test.Assert(t, "path", exps[x].path, gotNS.Node.Path) - test.Assert(t, "state", exps[x].state, gotNS.State) - x++ - - dw.Stop() -} - // // Test renaming sub-directory being watched. // @@ -270,6 +74,9 @@ func TestDirWatcher_renameDirectory(t *testing.T) { <-dw.C <-dw.C + // Wait for all watcher finished. + time.Sleep(400 * time.Millisecond) + var expDirs = []string{ "/newsubdir", } diff --git a/lib/memfs/watcher_example_test.go b/lib/memfs/watcher_example_test.go new file mode 100644 index 00000000..9ef7d8e2 --- /dev/null +++ b/lib/memfs/watcher_example_test.go @@ -0,0 +1,82 @@ +// Copyright 2022, Shulhan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package memfs + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "time" +) + +func ExampleNewWatcher() { + var ( + content = "Content of file" + + f *os.File + watcher *Watcher + ns NodeState + err error + ) + + // Create a file to be watched. + f, err = ioutil.TempFile("", "watcher") + if err != nil { + log.Fatal(err) + } + + watcher, err = NewWatcher(f.Name(), 150*time.Millisecond) + if err != nil { + log.Fatal(err) + } + + // Update file mode. + err = f.Chmod(0700) + if err != nil { + log.Fatal(err) + } + + ns = <-watcher.C + fmt.Printf("State: %s\n", ns.State) + fmt.Printf("File mode: %s\n", ns.Node.Mode()) + fmt.Printf("File size: %d\n", ns.Node.Size()) + + // Update content of file. + _, err = f.WriteString(content) + if err != nil { + log.Fatal(err) + } + ns = <-watcher.C + fmt.Printf("State: %s\n", ns.State) + fmt.Printf("File mode: %s\n", ns.Node.Mode()) + fmt.Printf("File size: %d\n", ns.Node.Size()) + + err = f.Close() + if err != nil { + log.Fatal(err) + } + + // Remove the file. + err = os.Remove(f.Name()) + if err != nil { + log.Fatal(err) + } + ns = <-watcher.C + fmt.Printf("State: %s\n", ns.State) + fmt.Printf("File mode: %s\n", ns.Node.Mode()) + fmt.Printf("File size: %d\n", ns.Node.Size()) + + //Output: + //State: FileStateUpdateMode + //File mode: -rwx------ + //File size: 0 + //State: FileStateUpdateContent + //File mode: -rwx------ + //File size: 15 + //State: FileStateDeleted + //File mode: -rwx------ + //File size: 15 +} diff --git a/lib/memfs/watcher_test.go b/lib/memfs/watcher_test.go deleted file mode 100644 index 30693b7f..00000000 --- a/lib/memfs/watcher_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2018, Shulhan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package memfs - -import ( - "io/ioutil" - "os" - "testing" - "time" - - "github.com/shuLhan/share/lib/test" -) - -type caseWatcher struct { - state FileState - mode os.FileMode - size int64 -} - -func TestWatcher(t *testing.T) { - var ( - content = "Write changes" - - f *os.File - watcher *Watcher - gotNS NodeState - err error - x int - ) - - f, err = ioutil.TempFile("", "watcher") - if err != nil { - t.Fatal(err) - } - - exps := []caseWatcher{{ - state: FileStateUpdateMode, - mode: 0700, - }, { - state: FileStateUpdateContent, - mode: 0700, - size: int64(len(content)), - }, { - state: FileStateDeleted, - mode: 0700, - size: int64(len(content)), - }} - - watcher, err = NewWatcher(f.Name(), 150*time.Millisecond) - if err != nil { - t.Fatal(err) - } - - // Update file mode - err = f.Chmod(0700) - if err != nil { - t.Fatal(err) - } - gotNS = <-watcher.C - test.Assert(t, "state", exps[x].state, gotNS.State) - test.Assert(t, "file mode", exps[x].mode, gotNS.Node.Mode()) - test.Assert(t, "file size", exps[x].size, gotNS.Node.Size()) - x++ - - _, err = f.WriteString(content) - if err != nil { - t.Fatal(err) - } - gotNS = <-watcher.C - test.Assert(t, "state", exps[x].state, gotNS.State) - test.Assert(t, "file mode", exps[x].mode, gotNS.Node.Mode()) - test.Assert(t, "file size", exps[x].size, gotNS.Node.Size()) - x++ - - err = f.Close() - if err != nil { - t.Fatal(err) - } - - err = os.Remove(f.Name()) - if err != nil { - t.Fatal(err) - } - gotNS = <-watcher.C - test.Assert(t, "state", exps[x].state, gotNS.State) - test.Assert(t, "file mode", exps[x].mode, gotNS.Node.Mode()) - test.Assert(t, "file size", exps[x].size, gotNS.Node.Size()) - x++ -} -- cgit v1.3