github.com/vlifesystems/rulehunter@v0.0.0-20180501090014-673078aa4a83/watcher/watcher_test.go (about)

     1  package watcher
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/vlifesystems/rulehunter/fileinfo"
     6  	"github.com/vlifesystems/rulehunter/internal/testhelpers"
     7  	"github.com/vlifesystems/rulehunter/quitter"
     8  	"os"
     9  	"path/filepath"
    10  	"reflect"
    11  	"sort"
    12  	"testing"
    13  	"time"
    14  )
    15  
    16  // Test initial filenames
    17  func TestWatch_1(t *testing.T) {
    18  	tmpDir := testhelpers.TempDir(t)
    19  	defer os.RemoveAll(tmpDir)
    20  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir)
    21  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.yaml"), tmpDir)
    22  	testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir)
    23  
    24  	files := make(chan fileinfo.FileInfo, 100)
    25  	logger := testhelpers.NewLogger()
    26  	quit := quitter.New()
    27  	period := 50 * time.Millisecond
    28  	go logger.Run(quit)
    29  	go Watch(tmpDir, period, logger, quit, files)
    30  	time.Sleep(200 * time.Millisecond)
    31  	quit.Quit()
    32  
    33  	wantNewFiles := map[string]int{
    34  		"debt.json": 1,
    35  		"debt.yaml": 1,
    36  		"flow.yaml": 1,
    37  	}
    38  	wantNonNewFiles := map[string]int{
    39  		"debt.json": 2,
    40  		"debt.yaml": 2,
    41  		"flow.yaml": 2,
    42  	}
    43  	err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files)
    44  	if err != nil {
    45  		t.Error("Watch:", err)
    46  	}
    47  
    48  	if logEntries := logger.GetEntries(); len(logEntries) != 0 {
    49  		t.Errorf("Watch: gotLogEntries: %v, wanted: []", logEntries)
    50  	}
    51  }
    52  
    53  // Test adding a filename to directory
    54  func TestWatch_2(t *testing.T) {
    55  	tmpDir := testhelpers.TempDir(t)
    56  	defer os.RemoveAll(tmpDir)
    57  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir)
    58  	testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir)
    59  
    60  	files := make(chan fileinfo.FileInfo, 100)
    61  	logger := testhelpers.NewLogger()
    62  	quit := quitter.New()
    63  	period := 50 * time.Millisecond
    64  	go logger.Run(quit)
    65  	go Watch(tmpDir, period, logger, quit, files)
    66  	time.Sleep(100 * time.Millisecond)
    67  
    68  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.yaml"), tmpDir)
    69  	time.Sleep(60 * time.Millisecond)
    70  	quit.Quit()
    71  
    72  	wantNewFiles := map[string]int{
    73  		"debt.json": 1,
    74  		"debt.yaml": 1,
    75  		"flow.yaml": 1,
    76  	}
    77  	wantNonNewFiles := map[string]int{
    78  		"debt.json": 2,
    79  		"flow.yaml": 2,
    80  		"debt.yaml": 0,
    81  	}
    82  	err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files)
    83  	if err != nil {
    84  		t.Error("Watch:", err)
    85  	}
    86  	if logEntries := logger.GetEntries(); len(logEntries) != 0 {
    87  		t.Errorf("Watch: gotLogEntries: %v, wanted: []", logEntries)
    88  	}
    89  }
    90  
    91  // Test changing a file
    92  func TestWatch_3(t *testing.T) {
    93  	tmpDir := testhelpers.TempDir(t)
    94  	defer os.RemoveAll(tmpDir)
    95  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir)
    96  	testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir)
    97  
    98  	files := make(chan fileinfo.FileInfo, 100)
    99  	logger := testhelpers.NewLogger()
   100  	quit := quitter.New()
   101  	period := 50 * time.Millisecond
   102  	go logger.Run(quit)
   103  	go Watch(tmpDir, period, logger, quit, files)
   104  	time.Sleep(100 * time.Millisecond)
   105  
   106  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir)
   107  	time.Sleep(100 * time.Millisecond)
   108  	quit.Quit()
   109  
   110  	wantNewFiles := map[string]int{
   111  		"debt.json": 2,
   112  		"flow.yaml": 1,
   113  	}
   114  	wantNonNewFiles := map[string]int{
   115  		"debt.json": 1,
   116  		"flow.yaml": 2,
   117  	}
   118  	err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files)
   119  	if err != nil {
   120  		t.Error("Watch:", err)
   121  	}
   122  	if logEntries := logger.GetEntries(); len(logEntries) != 0 {
   123  		t.Errorf("Watch: gotLogEntries: %v, wanted: []", logEntries)
   124  	}
   125  }
   126  
   127  func TestWatch_errors(t *testing.T) {
   128  	tmpDir := testhelpers.TempDir(t)
   129  	os.RemoveAll(tmpDir)
   130  	dir := filepath.Join(tmpDir, "non")
   131  	files := make(chan fileinfo.FileInfo, 100)
   132  	logger := testhelpers.NewLogger()
   133  	quit := quitter.New()
   134  	period := 50 * time.Millisecond
   135  	go logger.Run(quit)
   136  	go Watch(dir, period, logger, quit, files)
   137  	time.Sleep(100 * time.Millisecond)
   138  	quit.Quit()
   139  
   140  	wantNewFiles := map[string]int{}
   141  	wantNonNewFiles := map[string]int{}
   142  	wantLogEntries := []testhelpers.Entry{
   143  		testhelpers.Entry{
   144  			Level: testhelpers.Error,
   145  			Msg:   DirError(dir).Error(),
   146  		},
   147  	}
   148  
   149  	err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files)
   150  	if err != nil {
   151  		t.Error("Watch:", err)
   152  	}
   153  	if !reflect.DeepEqual(wantLogEntries, logger.GetEntries()) {
   154  		t.Errorf("Watch: gotLogEntries: %v, want: %v",
   155  			logger.GetEntries(), wantLogEntries)
   156  	}
   157  }
   158  
   159  // Test a directory being removed part way through watching
   160  func TestWatch_errors2(t *testing.T) {
   161  	tmpDir := testhelpers.TempDir(t)
   162  	files := make(chan fileinfo.FileInfo, 100)
   163  	logger := testhelpers.NewLogger()
   164  	quit := quitter.New()
   165  	period := 50 * time.Millisecond
   166  	go logger.Run(quit)
   167  	go Watch(tmpDir, period, logger, quit, files)
   168  	time.Sleep(100 * time.Millisecond)
   169  
   170  	os.RemoveAll(tmpDir)
   171  	time.Sleep(100 * time.Millisecond)
   172  	quit.Quit()
   173  
   174  	wantNewFiles := map[string]int{}
   175  	wantNonNewFiles := map[string]int{}
   176  	wantLogEntries := []testhelpers.Entry{
   177  		testhelpers.Entry{
   178  			Level: testhelpers.Error,
   179  			Msg:   DirError(tmpDir).Error(),
   180  		},
   181  	}
   182  
   183  	err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files)
   184  	if err != nil {
   185  		t.Error("Watch:", err)
   186  	}
   187  	if !reflect.DeepEqual(wantLogEntries, logger.GetEntries()) {
   188  		t.Errorf("Watch: gotLogEntries: %v, want: %v",
   189  			logger.GetEntries(), wantLogEntries)
   190  	}
   191  }
   192  
   193  func TestGetExperimentFilenames(t *testing.T) {
   194  	tmpDir := testhelpers.TempDir(t)
   195  	defer os.RemoveAll(tmpDir)
   196  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir)
   197  	testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.yaml"), tmpDir)
   198  	testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir)
   199  	testhelpers.CopyFile(
   200  		t,
   201  		filepath.Join("fixtures", "flow.yaml"),
   202  		tmpDir,
   203  		"flow.txt",
   204  	)
   205  
   206  	wantFiles := []string{"debt.json", "debt.yaml", "flow.yaml"}
   207  	gotFiles, err := GetExperimentFiles(tmpDir)
   208  	if err != nil {
   209  		t.Fatalf("GetExperimentFilenames: %v", err)
   210  	}
   211  	if err := checkCorrectFiles(gotFiles, wantFiles); err != nil {
   212  		t.Error("GetExperimentFiles:", err)
   213  	}
   214  }
   215  
   216  func TestGetExperimentFilenames_errors(t *testing.T) {
   217  	tmpDir := testhelpers.TempDir(t)
   218  	defer os.RemoveAll(tmpDir)
   219  	dir := filepath.Join(tmpDir, "non")
   220  	wantFiles := []string{}
   221  	wantErr := DirError(dir)
   222  	gotFiles, err := GetExperimentFiles(dir)
   223  	if err == nil || err.Error() != wantErr.Error() {
   224  		t.Fatalf("GetExperimentFilenames: gotErr: %v, wantErr: %v", err, wantErr)
   225  	}
   226  
   227  	if err := checkCorrectFiles(gotFiles, wantFiles); err != nil {
   228  		t.Error("GetExperimentFiles:", err)
   229  	}
   230  }
   231  
   232  func TestDirErrorError(t *testing.T) {
   233  	dir := "/tmp/someplace"
   234  	want := "can not watch directory: /tmp/someplace"
   235  	got := DirError(dir).Error()
   236  	if got != want {
   237  		t.Errorf("Error: got: %s, want: %s", got, want)
   238  	}
   239  }
   240  
   241  /*********************************
   242   *    Helper functions
   243   *********************************/
   244  func checkCorrectFiles(
   245  	gotFiles []fileinfo.FileInfo,
   246  	wantFilenames []string,
   247  ) error {
   248  	allFilenames := []string{}
   249  	for _, file := range gotFiles {
   250  		allFilenames = append(allFilenames, file.Name())
   251  	}
   252  	if len(allFilenames) != len(wantFilenames) {
   253  		return fmt.Errorf("gotFiles: %v, wantFilenames: %v",
   254  			allFilenames, wantFilenames)
   255  	}
   256  	sort.Strings(allFilenames)
   257  	sort.Strings(wantFilenames)
   258  	if !reflect.DeepEqual(allFilenames, wantFilenames) {
   259  		return fmt.Errorf("gotFiles: %v, wantFilenames: %v",
   260  			allFilenames, wantFilenames)
   261  	}
   262  	return nil
   263  }
   264  
   265  // The int in the maps below indicates that has been seen at least x times
   266  func checkCorrectFileChan(
   267  	wantNewFiles map[string]int,
   268  	wantNonNewFiles map[string]int,
   269  	files <-chan fileinfo.FileInfo,
   270  ) error {
   271  	allFiles := []fileinfo.FileInfo{}
   272  	gotNewFiles := map[string]int{}
   273  	gotNonNewFiles := map[string]int{}
   274  	for file := range files {
   275  		isNew := true
   276  		for _, f := range allFiles {
   277  			if fileinfo.IsEqual(file, f) {
   278  				isNew = false
   279  				break
   280  			}
   281  		}
   282  		if isNew {
   283  			gotNewFiles[file.Name()]++
   284  		} else {
   285  			gotNonNewFiles[file.Name()]++
   286  		}
   287  		allFiles = append(allFiles, file)
   288  	}
   289  	if len(gotNewFiles) != len(wantNewFiles) {
   290  		return fmt.Errorf("gotNewFiles: %v, wantNewFiles: %v",
   291  			gotNewFiles, wantNewFiles)
   292  	}
   293  	if len(gotNewFiles) > len(wantNewFiles) {
   294  		return fmt.Errorf("gotNewFiles: %v, wantNewFiles: %v",
   295  			gotNewFiles, wantNewFiles)
   296  	}
   297  	for name, n := range wantNewFiles {
   298  		if n > gotNewFiles[name] {
   299  			return fmt.Errorf("gotNewFiles: %v, wantNewFiles: %v",
   300  				gotNewFiles, wantNewFiles)
   301  		}
   302  	}
   303  	if len(gotNonNewFiles) > len(wantNonNewFiles) {
   304  		return fmt.Errorf("gotNonNewFiles: %v, wantNonNewFiles: %v",
   305  			gotNonNewFiles, wantNonNewFiles)
   306  	}
   307  	for name, n := range wantNonNewFiles {
   308  		if n > gotNonNewFiles[name] {
   309  			return fmt.Errorf("gotNonNewFiles: %v, wantNonNewFiles: %v",
   310  				gotNonNewFiles, wantNonNewFiles)
   311  		}
   312  	}
   313  	return nil
   314  }