MCPcopy Create free account
hub / github.com/couchbase/sync_gateway / TestUserDeleteDuringChangesWithAccess

Function TestUserDeleteDuringChangesWithAccess

rest/user_api_test.go:919–969  ·  view source on GitHub ↗

Test user delete while that user has an active changes feed (see issue 809)

(t *testing.T)

Source from the content-addressed store, hash-verified

917
918// Test user delete while that user has an active changes feed (see issue 809)
919func TestUserDeleteDuringChangesWithAccess(t *testing.T) {
920
921 base.SetUpTestLogging(t, base.LevelInfo, base.KeyChanges, base.KeyCache, base.KeyHTTP)
922
923 rtConfig := RestTesterConfig{SyncFn: `function(doc) {channel(doc.channel); if(doc.type == "setaccess") { access(doc.owner, doc.channel);}}`}
924 rt := NewRestTester(t, &rtConfig)
925 defer rt.Close()
926
927 response := rt.SendAdminRequest("PUT", "/db/_user/bernard", `{"name":"bernard", "password":"letmein", "admin_channels":["foo"]}`)
928 RequireStatus(t, response, 201)
929
930 var wg sync.WaitGroup
931 wg.Add(1)
932 go func() {
933 defer wg.Done()
934 changesResponse := rt.Send(RequestByUser("GET", "/{{.keyspace}}/_changes?feed=continuous&since=0&timeout=3000", "", "bernard"))
935 // When testing single threaded, this reproduces the issue described in #809.
936 // When testing multithreaded (-cpu 4 -race), there are three (valid) possibilities"
937 // 1. The DELETE gets processed before the _changes auth completes: this will return 401
938 // 2. The _changes request gets processed before the DELETE: the changes response will be closed when the user is deleted
939 // 3. The DELETE is processed after the _changes auth completes, but before the MultiChangesFeed is instantiated. The
940 // changes feed doesn't have a trigger to attempt a reload of the user in this scenario, so will continue until disconnected
941 // by the client. This should be fixed more generally (to terminate all active user sessions when the user is deleted, not just
942 // changes feeds) but that enhancement is too high risk to introduce at this time. The timeout on changes will terminate the unit
943 // test.
944 if changesResponse.Code == 401 {
945 // case 1 - ok
946 } else {
947 // case 2 - ensure no error processing the changes response. The number of entries may vary, depending
948 // on whether the changes loop performed an additional iteration before catching the deleted user.
949 _, err := rt.ReadContinuousChanges(changesResponse)
950 assert.NoError(t, err)
951 }
952 }()
953
954 // TODO: sleep required to ensure the changes feed iteration starts before the delete gets processed.
955 time.Sleep(500 * time.Millisecond)
956 rt.SendAdminRequest("PUT", "/{{.keyspace}}/bernard_doc1", `{"type":"setaccess", "owner":"bernard","channel":"foo"}`)
957 rt.SendAdminRequest("DELETE", "/db/_user/bernard", "")
958 rt.SendAdminRequest("PUT", "/{{.keyspace}}/manny_doc1", `{"type":"setaccess", "owner":"manny","channel":"bar"}`)
959 rt.SendAdminRequest("PUT", "/{{.keyspace}}/bernard_doc2", `{"type":"general", "channel":"foo"}`)
960
961 // case 3
962 for i := 0; i <= 5; i++ {
963 docId := fmt.Sprintf("/{{.keyspace}}/bernard_doc%d", i+3)
964 response = rt.SendAdminRequest("PUT", docId, `{"type":"setaccess", "owner":"bernard", "channel":"foo"}`)
965 RequireStatus(t, response, http.StatusCreated)
966 }
967
968 wg.Wait()
969}
970
971// Helper functions
972

Callers

nothing calls this directly

Calls 11

CloseMethod · 0.95
SendAdminRequestMethod · 0.95
SendMethod · 0.95
ReadContinuousChangesMethod · 0.95
SetUpTestLoggingFunction · 0.92
NewRestTesterFunction · 0.85
RequireStatusFunction · 0.85
RequestByUserFunction · 0.85
DoneMethod · 0.80
AddMethod · 0.45
WaitMethod · 0.45

Tested by

no test coverage detected