go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/_motor/providers/os/events/watcher_test.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package events
     5  
     6  import (
     7  	"io/ioutil"
     8  	"path/filepath"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"go.mondoo.com/cnquery/motor/providers"
    14  	"go.mondoo.com/cnquery/motor/providers/mock"
    15  
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  type WatcherTester struct {
    21  	mock    providers.Instance
    22  	watcher *Watcher
    23  }
    24  
    25  func SetupWatcherTest() *WatcherTester {
    26  	filepath, _ := filepath.Abs("testdata/watcher_test.toml")
    27  	trans, _ := mock.NewFromTomlFile(filepath)
    28  	return &WatcherTester{watcher: NewWatcher(trans), mock: trans}
    29  }
    30  
    31  func TeardownWatcherTest(wt *WatcherTester) {
    32  	wt.watcher.TearDown()
    33  }
    34  
    35  func TestCommandSubscribe(t *testing.T) {
    36  	var wg sync.WaitGroup
    37  	wt := SetupWatcherTest()
    38  	w := wt.watcher
    39  
    40  	var res *CommandObservable
    41  	wg.Add(1)
    42  	w.Subscribe("command", "hostname", func(co providers.Observable) {
    43  		switch x := co.(type) {
    44  		case *CommandObservable:
    45  			defer wg.Done()
    46  			res = x
    47  		default:
    48  		}
    49  	})
    50  	wg.Wait()
    51  
    52  	stdout, err := ioutil.ReadAll(res.Result.Stdout)
    53  	assert.Nil(t, err, "could extract stdout")
    54  	assert.Equal(t, "mockland.local", string(stdout), "get the expected command output")
    55  	TeardownWatcherTest(wt)
    56  }
    57  
    58  func TestFileSubscribe(t *testing.T) {
    59  	var wg sync.WaitGroup
    60  	wt := SetupWatcherTest()
    61  	w := wt.watcher
    62  
    63  	var res *FileObservable
    64  
    65  	wg.Add(1)
    66  	err := w.Subscribe("file", "/tmp/test", func(fo providers.Observable) {
    67  		switch x := fo.(type) {
    68  		case *FileObservable:
    69  			defer wg.Done()
    70  			res = x
    71  		default:
    72  		}
    73  	})
    74  	require.NoError(t, err)
    75  	wg.Wait()
    76  	content, err := ioutil.ReadAll(res.File)
    77  	assert.Nil(t, err, "file content was returned without any error")
    78  	assert.Equal(t, "test", string(content), "get the expected command output")
    79  
    80  	TeardownWatcherTest(wt)
    81  }
    82  
    83  func TestFileChangeEvents(t *testing.T) {
    84  	var waitInitialRead sync.WaitGroup
    85  	var waitFileUpdate sync.WaitGroup
    86  	var waitSecondRead sync.WaitGroup
    87  
    88  	wt := SetupWatcherTest()
    89  	w := wt.watcher
    90  	// wait 500ms
    91  	w.SleepDuration = time.Duration(2 * time.Millisecond)
    92  
    93  	res := []string{}
    94  	readCount := 0
    95  	waitInitialRead.Add(1)
    96  	waitFileUpdate.Add(1)
    97  	waitSecondRead.Add(1)
    98  
    99  	err := w.Subscribe("file", "/tmp/test", func(fo providers.Observable) {
   100  		switch x := fo.(type) {
   101  		case *FileObservable:
   102  			if readCount == 0 {
   103  				defer waitInitialRead.Done()
   104  			} else if readCount == 1 {
   105  				waitFileUpdate.Wait()
   106  				defer waitSecondRead.Done()
   107  			} else {
   108  				return
   109  			}
   110  			content, err := ioutil.ReadAll(x.File)
   111  			if err == nil {
   112  				res = append(res, string(content))
   113  			}
   114  			readCount++
   115  		default:
   116  		}
   117  	})
   118  	require.NoError(t, err)
   119  
   120  	waitInitialRead.Wait()
   121  
   122  	// change file content
   123  	mt := wt.mock.(*mock.Provider)
   124  	mt.Fs.Files["/tmp/test"].Content = "newtest"
   125  	waitFileUpdate.Done()
   126  
   127  	waitSecondRead.Wait()
   128  
   129  	assert.Equal(t, []string{"test", "newtest"}, res, "detect file change")
   130  
   131  	TeardownWatcherTest(wt)
   132  }