github.com/netdata/go.d.plugin@v0.58.1/modules/filecheck/filecheck_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package filecheck
     4  
     5  import (
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/netdata/go.d.plugin/agent/module"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestNew(t *testing.T) {
    16  	assert.Implements(t, (*module.Module)(nil), New())
    17  }
    18  
    19  func TestFilecheck_Cleanup(t *testing.T) {
    20  	assert.NotPanics(t, New().Cleanup)
    21  }
    22  
    23  func TestFilecheck_Init(t *testing.T) {
    24  	tests := map[string]struct {
    25  		config          Config
    26  		wantNumOfCharts int
    27  		wantFail        bool
    28  	}{
    29  		"default": {
    30  			config:   New().Config,
    31  			wantFail: true,
    32  		},
    33  		"empty files->include and dirs->include": {
    34  			config: Config{
    35  				Files: filesConfig{},
    36  				Dirs:  dirsConfig{},
    37  			},
    38  			wantFail: true,
    39  		},
    40  		"files->include and dirs->include": {
    41  			config: Config{
    42  				Files: filesConfig{
    43  					Include: []string{
    44  						"/path/to/file1",
    45  						"/path/to/file2",
    46  					},
    47  				},
    48  				Dirs: dirsConfig{
    49  					Include: []string{
    50  						"/path/to/dir1",
    51  						"/path/to/dir2",
    52  					},
    53  					CollectDirSize: true,
    54  				},
    55  			},
    56  			wantNumOfCharts: len(fileCharts) + len(dirCharts),
    57  		},
    58  		"only files->include": {
    59  			config: Config{
    60  				Files: filesConfig{
    61  					Include: []string{
    62  						"/path/to/file1",
    63  						"/path/to/file2",
    64  					},
    65  				},
    66  			},
    67  			wantNumOfCharts: len(fileCharts),
    68  		},
    69  		"only dirs->include": {
    70  			config: Config{
    71  				Dirs: dirsConfig{
    72  					Include: []string{
    73  						"/path/to/dir1",
    74  						"/path/to/dir2",
    75  					},
    76  					CollectDirSize: true,
    77  				},
    78  			},
    79  			wantNumOfCharts: len(dirCharts),
    80  		},
    81  	}
    82  
    83  	for name, test := range tests {
    84  		t.Run(name, func(t *testing.T) {
    85  			fc := New()
    86  			fc.Config = test.config
    87  
    88  			if test.wantFail {
    89  				assert.False(t, fc.Init())
    90  			} else {
    91  				require.True(t, fc.Init())
    92  				assert.Equal(t, test.wantNumOfCharts, len(*fc.Charts()))
    93  			}
    94  		})
    95  	}
    96  }
    97  
    98  func TestFilecheck_Check(t *testing.T) {
    99  	tests := map[string]struct {
   100  		prepare func() *Filecheck
   101  	}{
   102  		"collect files":                   {prepare: prepareFilecheckFiles},
   103  		"collect files filepath pattern":  {prepare: prepareFilecheckGlobFiles},
   104  		"collect only non existent files": {prepare: prepareFilecheckNonExistentFiles},
   105  		"collect dirs":                    {prepare: prepareFilecheckDirs},
   106  		"collect dirs filepath pattern":   {prepare: prepareFilecheckGlobDirs},
   107  		"collect only non existent dirs":  {prepare: prepareFilecheckNonExistentDirs},
   108  		"collect files and dirs":          {prepare: prepareFilecheckFilesDirs},
   109  	}
   110  
   111  	for name, test := range tests {
   112  		t.Run(name, func(t *testing.T) {
   113  			fc := test.prepare()
   114  			require.True(t, fc.Init())
   115  
   116  			assert.True(t, fc.Check())
   117  		})
   118  	}
   119  }
   120  
   121  func TestFilecheck_Collect(t *testing.T) {
   122  	// TODO: should use TEMP dir and create files/dirs dynamically during a test case
   123  	tests := map[string]struct {
   124  		prepare       func() *Filecheck
   125  		wantCollected map[string]int64
   126  	}{
   127  		"collect files": {
   128  			prepare: prepareFilecheckFiles,
   129  			wantCollected: map[string]int64{
   130  				"file_testdata/empty_file.log_exists":        1,
   131  				"file_testdata/empty_file.log_mtime_ago":     5081,
   132  				"file_testdata/empty_file.log_size_bytes":    0,
   133  				"file_testdata/file.log_exists":              1,
   134  				"file_testdata/file.log_mtime_ago":           4161,
   135  				"file_testdata/file.log_size_bytes":          5707,
   136  				"file_testdata/non_existent_file.log_exists": 0,
   137  				"num_of_files": 3,
   138  				"num_of_dirs":  0,
   139  			},
   140  		},
   141  		"collect files filepath pattern": {
   142  			prepare: prepareFilecheckGlobFiles,
   143  			wantCollected: map[string]int64{
   144  				"file_testdata/empty_file.log_exists":     1,
   145  				"file_testdata/empty_file.log_mtime_ago":  5081,
   146  				"file_testdata/empty_file.log_size_bytes": 0,
   147  				"file_testdata/file.log_exists":           1,
   148  				"file_testdata/file.log_mtime_ago":        4161,
   149  				"file_testdata/file.log_size_bytes":       5707,
   150  				"num_of_files":                            2,
   151  				"num_of_dirs":                             0,
   152  			},
   153  		},
   154  		"collect only non existent files": {
   155  			prepare: prepareFilecheckNonExistentFiles,
   156  			wantCollected: map[string]int64{
   157  				"file_testdata/non_existent_file.log_exists": 0,
   158  				"num_of_files": 1,
   159  				"num_of_dirs":  0,
   160  			},
   161  		},
   162  		"collect dirs": {
   163  			prepare: prepareFilecheckDirs,
   164  			wantCollected: map[string]int64{
   165  				"dir_testdata/dir_exists":              1,
   166  				"dir_testdata/dir_mtime_ago":           4087,
   167  				"dir_testdata/dir_num_of_files":        3,
   168  				"dir_testdata/dir_size_bytes":          8160,
   169  				"dir_testdata/non_existent_dir_exists": 0,
   170  				"num_of_files":                         0,
   171  				"num_of_dirs":                          2,
   172  			},
   173  		},
   174  		"collect dirs filepath pattern": {
   175  			prepare: prepareFilecheckGlobDirs,
   176  			wantCollected: map[string]int64{
   177  				"dir_testdata/dir_exists":              1,
   178  				"dir_testdata/dir_mtime_ago":           4087,
   179  				"dir_testdata/dir_num_of_files":        3,
   180  				"dir_testdata/dir_size_bytes":          8160,
   181  				"dir_testdata/non_existent_dir_exists": 0,
   182  				"num_of_files":                         0,
   183  				"num_of_dirs":                          2,
   184  			},
   185  		},
   186  		"collect dirs w/o size": {
   187  			prepare: prepareFilecheckDirsWithoutSize,
   188  			wantCollected: map[string]int64{
   189  				"dir_testdata/dir_exists":              1,
   190  				"dir_testdata/dir_mtime_ago":           4087,
   191  				"dir_testdata/dir_num_of_files":        3,
   192  				"dir_testdata/non_existent_dir_exists": 0,
   193  				"num_of_files":                         0,
   194  				"num_of_dirs":                          2,
   195  			},
   196  		},
   197  		"collect only non existent dirs": {
   198  			prepare: prepareFilecheckNonExistentDirs,
   199  			wantCollected: map[string]int64{
   200  				"dir_testdata/non_existent_dir_exists": 0,
   201  				"num_of_files":                         0,
   202  				"num_of_dirs":                          1,
   203  			},
   204  		},
   205  		"collect files and dirs": {
   206  			prepare: prepareFilecheckFilesDirs,
   207  			wantCollected: map[string]int64{
   208  				"dir_testdata/dir_exists":                    1,
   209  				"dir_testdata/dir_mtime_ago":                 4120,
   210  				"dir_testdata/dir_num_of_files":              3,
   211  				"dir_testdata/dir_size_bytes":                8160,
   212  				"dir_testdata/non_existent_dir_exists":       0,
   213  				"file_testdata/empty_file.log_exists":        1,
   214  				"file_testdata/empty_file.log_mtime_ago":     5176,
   215  				"file_testdata/empty_file.log_size_bytes":    0,
   216  				"file_testdata/file.log_exists":              1,
   217  				"file_testdata/file.log_mtime_ago":           4256,
   218  				"file_testdata/file.log_size_bytes":          5707,
   219  				"file_testdata/non_existent_file.log_exists": 0,
   220  				"num_of_files":                               3,
   221  				"num_of_dirs":                                2,
   222  			},
   223  		},
   224  	}
   225  
   226  	for name, test := range tests {
   227  		t.Run(name, func(t *testing.T) {
   228  			fc := test.prepare()
   229  			require.True(t, fc.Init())
   230  
   231  			collected := fc.Collect()
   232  
   233  			copyModTime(test.wantCollected, collected)
   234  			assert.Equal(t, test.wantCollected, collected)
   235  			ensureCollectedHasAllChartsDimsVarsIDs(t, fc, collected)
   236  		})
   237  	}
   238  }
   239  
   240  func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, fc *Filecheck, collected map[string]int64) {
   241  	// TODO: check other charts
   242  	for _, chart := range *fc.Charts() {
   243  		if chart.Obsolete {
   244  			continue
   245  		}
   246  		switch chart.ID {
   247  		case fileExistenceChart.ID, dirExistenceChart.ID:
   248  			for _, dim := range chart.Dims {
   249  				_, ok := collected[dim.ID]
   250  				assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID)
   251  			}
   252  			for _, v := range chart.Vars {
   253  				_, ok := collected[v.ID]
   254  				assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID)
   255  			}
   256  		}
   257  	}
   258  }
   259  
   260  func prepareFilecheckFiles() *Filecheck {
   261  	fc := New()
   262  	fc.Config.Files.Include = []string{
   263  		"testdata/empty_file.log",
   264  		"testdata/file.log",
   265  		"testdata/non_existent_file.log",
   266  	}
   267  	return fc
   268  }
   269  
   270  func prepareFilecheckGlobFiles() *Filecheck {
   271  	fc := New()
   272  	fc.Config.Files.Include = []string{
   273  		"testdata/*.log",
   274  	}
   275  	return fc
   276  }
   277  
   278  func prepareFilecheckNonExistentFiles() *Filecheck {
   279  	fc := New()
   280  	fc.Config.Files.Include = []string{
   281  		"testdata/non_existent_file.log",
   282  	}
   283  	return fc
   284  }
   285  
   286  func prepareFilecheckDirs() *Filecheck {
   287  	fc := New()
   288  	fc.Config.Dirs.Include = []string{
   289  		"testdata/dir",
   290  		"testdata/non_existent_dir",
   291  	}
   292  	return fc
   293  }
   294  
   295  func prepareFilecheckGlobDirs() *Filecheck {
   296  	fc := New()
   297  	fc.Config.Dirs.Include = []string{
   298  		"testdata/*ir",
   299  		"testdata/non_existent_dir",
   300  	}
   301  	return fc
   302  }
   303  
   304  func prepareFilecheckDirsWithoutSize() *Filecheck {
   305  	fc := New()
   306  	fc.Config.Dirs.Include = []string{
   307  		"testdata/dir",
   308  		"testdata/non_existent_dir",
   309  	}
   310  	fc.Config.Dirs.CollectDirSize = false
   311  	return fc
   312  }
   313  
   314  func prepareFilecheckNonExistentDirs() *Filecheck {
   315  	fc := New()
   316  	fc.Config.Dirs.Include = []string{
   317  		"testdata/non_existent_dir",
   318  	}
   319  	return fc
   320  }
   321  
   322  func prepareFilecheckFilesDirs() *Filecheck {
   323  	fc := New()
   324  	fc.Config.Files.Include = []string{
   325  		"testdata/empty_file.log",
   326  		"testdata/file.log",
   327  		"testdata/non_existent_file.log",
   328  	}
   329  	fc.Config.Dirs.Include = []string{
   330  		"testdata/dir",
   331  		"testdata/non_existent_dir",
   332  	}
   333  	return fc
   334  }
   335  
   336  func copyModTime(dst, src map[string]int64) {
   337  	if src == nil || dst == nil {
   338  		return
   339  	}
   340  	for key := range src {
   341  		if strings.Contains(key, "mtime") {
   342  			dst[key] = src[key]
   343  		}
   344  	}
   345  }