github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/job/trigger_event_test.go (about)

     1  package job_test
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/cozy/cozy-stack/model/job"
    10  	"github.com/cozy/cozy-stack/pkg/config/config"
    11  	"github.com/cozy/cozy-stack/pkg/couchdb"
    12  	"github.com/cozy/cozy-stack/pkg/realtime"
    13  	"github.com/cozy/cozy-stack/tests/testutils"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestTrigger(t *testing.T) {
    19  	if testing.Short() {
    20  		t.Skip("an instance is required for this test: test skipped due to the use of --short flag")
    21  	}
    22  
    23  	config.UseTestFile(t)
    24  	setup := testutils.NewSetup(t, t.Name())
    25  	testInstance := setup.GetTestInstance()
    26  
    27  	t.Run("TriggerEvent", func(t *testing.T) {
    28  		var wg sync.WaitGroup
    29  		called := make(map[string]bool)
    30  		verb := "CREATED"
    31  
    32  		bro := job.NewMemBroker()
    33  		assert.NoError(t, bro.StartWorkers(job.WorkersList{
    34  			{
    35  				WorkerType:   "worker_event",
    36  				Concurrency:  1,
    37  				MaxExecCount: 1,
    38  				Timeout:      1 * time.Millisecond,
    39  				WorkerFunc: func(ctx *job.TaskContext) error {
    40  					defer wg.Done()
    41  					var msg string
    42  					if err := ctx.UnmarshalMessage(&msg); err != nil {
    43  						assert.NoError(t, err)
    44  						return err
    45  					}
    46  					var evt struct {
    47  						Domain string `json:"domain"`
    48  						Verb   string `json:"verb"`
    49  						Doc    couchdb.JSONDoc
    50  					}
    51  					if err := ctx.UnmarshalEvent(&evt); err != nil {
    52  						assert.NoError(t, err)
    53  						return nil
    54  					}
    55  					assert.Equal(t, testInstance.Domain, evt.Domain)
    56  					assert.Equal(t, verb, evt.Verb)
    57  					assert.Equal(t, "test-id", evt.Doc.ID())
    58  					called[msg] = true
    59  					return nil
    60  				},
    61  			},
    62  		}))
    63  
    64  		var triggers []job.Trigger
    65  		triggersInfos := []job.TriggerInfos{
    66  			{
    67  				Type:       "@event",
    68  				Arguments:  "io.cozy.testeventobject:DELETED",
    69  				WorkerType: "worker_event",
    70  				Message:    makeMessage(t, "message-bad-verb"),
    71  			},
    72  			{
    73  				Type:       "@event",
    74  				Arguments:  "io.cozy.testeventobject:CREATED:value:test",
    75  				WorkerType: "worker_event",
    76  				Message:    makeMessage(t, "message-correct-verb-correct-value"),
    77  			},
    78  			{
    79  				Type:       "@event",
    80  				Arguments:  "io.cozy.testeventobject:CREATED",
    81  				WorkerType: "worker_event",
    82  				Message:    makeMessage(t, "message-correct-verb"),
    83  			},
    84  			{
    85  				Type:       "@event",
    86  				Arguments:  "io.cozy.testeventobject:CREATED:notvalue:test",
    87  				WorkerType: "worker_event",
    88  				Message:    makeMessage(t, "message-correct-verb-bad-value"),
    89  			},
    90  			{
    91  				Type:       "@event",
    92  				Arguments:  "io.cozy.testeventobject:UPDATED:!=:test",
    93  				WorkerType: "worker_event",
    94  				Message:    makeMessage(t, "message-change"),
    95  			},
    96  			{
    97  				Type:       "@event",
    98  				Arguments:  "io.cozy.testeventobject",
    99  				WorkerType: "worker_event",
   100  				Message:    makeMessage(t, "message-wholetype"),
   101  			},
   102  		}
   103  
   104  		sch := job.NewMemScheduler()
   105  		assert.NoError(t, sch.StartScheduler(bro))
   106  
   107  		for _, infos := range triggersInfos {
   108  			trigger, err := job.NewTrigger(testInstance, infos, infos.Message)
   109  			require.NoError(t, err)
   110  
   111  			err = sch.AddTrigger(trigger)
   112  			require.NoError(t, err)
   113  
   114  			triggers = append(triggers, trigger)
   115  		}
   116  
   117  		wg.Add(3)
   118  
   119  		time.AfterFunc(1*time.Millisecond, func() {
   120  			doc := couchdb.JSONDoc{
   121  				Type: "io.cozy.testeventobject",
   122  				M: map[string]interface{}{
   123  					"_id":  "test-id",
   124  					"_rev": "1-xxabxx",
   125  					"test": "value",
   126  				},
   127  			}
   128  			realtime.GetHub().Publish(testInstance, realtime.EventCreate, &doc, nil)
   129  		})
   130  
   131  		wg.Wait()
   132  
   133  		assert.True(t, called["message-correct-verb"])
   134  		assert.True(t, called["message-correct-verb-correct-value"])
   135  		assert.True(t, called["message-wholetype"])
   136  		assert.False(t, called["message-bad-verb"])
   137  		assert.False(t, called["message-correct-verb-bad-value"])
   138  		assert.False(t, called["message-change"])
   139  
   140  		delete(called, "message-correct-verb")
   141  		delete(called, "message-correct-verb-correct-value")
   142  		delete(called, "message-wholetype")
   143  
   144  		wg.Add(1)
   145  		verb = "UPDATED"
   146  
   147  		time.AfterFunc(1*time.Millisecond, func() {
   148  			doc := couchdb.JSONDoc{
   149  				Type: "io.cozy.testeventobject",
   150  				M: map[string]interface{}{
   151  					"_id":  "test-id",
   152  					"_rev": "2-xxcdxx",
   153  					"test": "value",
   154  				},
   155  			}
   156  			olddoc := couchdb.JSONDoc{
   157  				Type: "io.cozy.testeventobject",
   158  				M: map[string]interface{}{
   159  					"_id":  "test-id",
   160  					"_rev": "1-xxabxx",
   161  					"test": "value",
   162  				},
   163  			}
   164  			realtime.GetHub().Publish(testInstance, realtime.EventUpdate, &doc, &olddoc)
   165  		})
   166  
   167  		wg.Wait()
   168  
   169  		assert.True(t, called["message-wholetype"])
   170  		assert.False(t, called["message-correct-verb"])
   171  		assert.False(t, called["message-correct-verb-correct-value"])
   172  		assert.False(t, called["message-bad-verb"])
   173  		assert.False(t, called["message-correct-verb-bad-value"])
   174  		assert.False(t, called["message-change"])
   175  
   176  		delete(called, "message-wholetype")
   177  
   178  		wg.Add(2)
   179  
   180  		time.AfterFunc(1*time.Millisecond, func() {
   181  			doc := couchdb.JSONDoc{
   182  				Type: "io.cozy.testeventobject",
   183  				M: map[string]interface{}{
   184  					"_id":  "test-id",
   185  					"_rev": "3-xxefxx",
   186  					"test": "changed",
   187  				},
   188  			}
   189  			olddoc := couchdb.JSONDoc{
   190  				Type: "io.cozy.testeventobject",
   191  				M: map[string]interface{}{
   192  					"_id":  "test-id",
   193  					"_rev": "2-xxcdxx",
   194  					"test": "value",
   195  				},
   196  			}
   197  			realtime.GetHub().Publish(testInstance, realtime.EventUpdate, &doc, &olddoc)
   198  		})
   199  
   200  		wg.Wait()
   201  
   202  		assert.False(t, called["message-correct-verb"])
   203  		assert.False(t, called["message-correct-verb-correct-value"])
   204  		assert.False(t, called["message-bad-verb"])
   205  		assert.False(t, called["message-correct-verb-bad-value"])
   206  		assert.True(t, called["message-change"])
   207  		assert.True(t, called["message-wholetype"])
   208  
   209  		for _, trigger := range triggers {
   210  			err := sch.DeleteTrigger(testInstance, trigger.ID())
   211  			assert.NoError(t, err)
   212  		}
   213  
   214  		err := sch.ShutdownScheduler(context.Background())
   215  		assert.NoError(t, err)
   216  	})
   217  }
   218  
   219  func makeMessage(t *testing.T, msg string) job.Message {
   220  	out, err := job.NewMessage(msg)
   221  	assert.NoError(t, err)
   222  	return out
   223  }