@@ -20,6 +20,7 @@ import (
20
20
21
21
sgbucket "github.com/couchbase/sg-bucket"
22
22
"github.com/couchbase/sync_gateway/base"
23
+ "github.com/couchbase/sync_gateway/channels"
23
24
"github.com/stretchr/testify/assert"
24
25
"github.com/stretchr/testify/require"
25
26
)
@@ -1872,3 +1873,181 @@ func TestPutExistingCurrentVersionWithNoExistingDoc(t *testing.T) {
1872
1873
assert .True (t , reflect .DeepEqual (syncData .HLV .PreviousVersions , pv ))
1873
1874
assert .Equal (t , "1-3a208ea66e84121b528f05b5457d1134" , syncData .CurrentRev )
1874
1875
}
1876
+
1877
+ // TestGetCVWithDocResidentInCache:
1878
+ // - Two test cases, one with doc a user will have access to, one without
1879
+ // - Purpose is to have a doc that is resident in rev cache and use the GetCV function to retrieve these docs
1880
+ // - Assert that the doc the user has access to is corrected fetched
1881
+ // - Assert the doc the user doesn't have access to is fetched but correctly redacted
1882
+ func TestGetCVWithDocResidentInCache (t * testing.T ) {
1883
+ const docID = "doc1"
1884
+
1885
+ testCases := []struct {
1886
+ name string
1887
+ docChannels []string
1888
+ access bool
1889
+ }{
1890
+ {
1891
+ name : "getCVWithUserAccess" ,
1892
+ docChannels : []string {"A" },
1893
+ access : true ,
1894
+ },
1895
+ {
1896
+ name : "getCVWithoutUserAccess" ,
1897
+ docChannels : []string {"B" },
1898
+ access : false ,
1899
+ },
1900
+ }
1901
+ for _ , testCase := range testCases {
1902
+ t .Run (testCase .name , func (t * testing.T ) {
1903
+ db , ctx := setupTestDB (t )
1904
+ defer db .Close (ctx )
1905
+ collection := GetSingleDatabaseCollectionWithUser (t , db )
1906
+ collection .ChannelMapper = channels .NewChannelMapper (ctx , channels .DocChannelsSyncFunction , db .Options .JavascriptTimeout )
1907
+
1908
+ // Create a user with access to channel A
1909
+ authenticator := db .Authenticator (base .TestCtx (t ))
1910
+ user , err := authenticator .NewUser ("alice" , "letmein" , channels .BaseSetOf (t , "A" ))
1911
+ require .NoError (t , err )
1912
+ require .NoError (t , authenticator .Save (user ))
1913
+ collection .user , err = authenticator .GetUser ("alice" )
1914
+ require .NoError (t , err )
1915
+
1916
+ // create doc with the channels for the test case
1917
+ docBody := Body {"channels" : testCase .docChannels }
1918
+ rev , doc , err := collection .Put (ctx , docID , docBody )
1919
+ require .NoError (t , err )
1920
+
1921
+ vrs := doc .HLV .Version
1922
+ src := doc .HLV .SourceID
1923
+ sv := & Version {Value : vrs , SourceID : src }
1924
+ revision , err := collection .GetCV (ctx , docID , sv , true )
1925
+ require .NoError (t , err )
1926
+ if testCase .access {
1927
+ assert .Equal (t , rev , revision .RevID )
1928
+ assert .Equal (t , sv , revision .CV )
1929
+ assert .Equal (t , docID , revision .DocID )
1930
+ assert .Equal (t , []byte (`{"channels":["A"]}` ), revision .BodyBytes )
1931
+ } else {
1932
+ assert .Equal (t , rev , revision .RevID )
1933
+ assert .Equal (t , sv , revision .CV )
1934
+ assert .Equal (t , docID , revision .DocID )
1935
+ assert .Equal (t , []byte (RemovedRedactedDocument ), revision .BodyBytes )
1936
+ }
1937
+ })
1938
+ }
1939
+ }
1940
+
1941
+ // TestGetByCVForDocNotResidentInCache:
1942
+ // - Setup db with rev cache size of 1
1943
+ // - Put two docs forcing eviction of the first doc
1944
+ // - Use GetCV function to fetch the first doc, forcing the rev cache to load the doc from bucket
1945
+ // - Assert the doc revision fetched is correct to the first doc we created
1946
+ func TestGetByCVForDocNotResidentInCache (t * testing.T ) {
1947
+ db , ctx := SetupTestDBWithOptions (t , DatabaseContextOptions {
1948
+ RevisionCacheOptions : & RevisionCacheOptions {
1949
+ Size : 1 ,
1950
+ },
1951
+ })
1952
+ defer db .Close (ctx )
1953
+ collection := GetSingleDatabaseCollectionWithUser (t , db )
1954
+ collection .ChannelMapper = channels .NewChannelMapper (ctx , channels .DocChannelsSyncFunction , db .Options .JavascriptTimeout )
1955
+
1956
+ // Create a user with access to channel A
1957
+ authenticator := db .Authenticator (base .TestCtx (t ))
1958
+ user , err := authenticator .NewUser ("alice" , "letmein" , channels .BaseSetOf (t , "A" ))
1959
+ require .NoError (t , err )
1960
+ require .NoError (t , authenticator .Save (user ))
1961
+ collection .user , err = authenticator .GetUser ("alice" )
1962
+ require .NoError (t , err )
1963
+
1964
+ const (
1965
+ doc1ID = "doc1"
1966
+ doc2ID = "doc2"
1967
+ )
1968
+
1969
+ revBody := Body {"channels" : []string {"A" }}
1970
+ rev , doc , err := collection .Put (ctx , doc1ID , revBody )
1971
+ require .NoError (t , err )
1972
+
1973
+ // put another doc that should evict first doc from cache
1974
+ _ , _ , err = collection .Put (ctx , doc2ID , revBody )
1975
+ require .NoError (t , err )
1976
+
1977
+ // get by CV should force a load from bucket and have a cache miss
1978
+ vrs := doc .HLV .Version
1979
+ src := doc .HLV .SourceID
1980
+ sv := & Version {Value : vrs , SourceID : src }
1981
+ revision , err := collection .GetCV (ctx , doc1ID , sv , true )
1982
+ require .NoError (t , err )
1983
+
1984
+ // assert the fetched doc is the first doc we added and assert that we did in fact get cache miss
1985
+ assert .Equal (t , int64 (1 ), db .DbStats .Cache ().RevisionCacheMisses .Value ())
1986
+ assert .Equal (t , rev , revision .RevID )
1987
+ assert .Equal (t , sv , revision .CV )
1988
+ assert .Equal (t , doc1ID , revision .DocID )
1989
+ assert .Equal (t , []byte (`{"channels":["A"]}` ), revision .BodyBytes )
1990
+ }
1991
+
1992
+ // TestGetCVActivePathway:
1993
+ // - Two test cases, one with doc a user will have access to, one without
1994
+ // - Purpose is top specify nil CV to the GetCV function to force the GetActive code pathway
1995
+ // - Assert doc that is created is fetched correctly when user has access to doc
1996
+ // - Assert that correct error is returned when user has no access to the doc
1997
+ func TestGetCVActivePathway (t * testing.T ) {
1998
+ const docID = "doc1"
1999
+
2000
+ testCases := []struct {
2001
+ name string
2002
+ docChannels []string
2003
+ access bool
2004
+ }{
2005
+ {
2006
+ name : "activeFetchWithUserAccess" ,
2007
+ docChannels : []string {"A" },
2008
+ access : true ,
2009
+ },
2010
+ {
2011
+ name : "activeFetchWithoutUserAccess" ,
2012
+ docChannels : []string {"B" },
2013
+ access : false ,
2014
+ },
2015
+ }
2016
+ for _ , testCase := range testCases {
2017
+ t .Run (testCase .name , func (t * testing.T ) {
2018
+ db , ctx := setupTestDB (t )
2019
+ defer db .Close (ctx )
2020
+ collection := GetSingleDatabaseCollectionWithUser (t , db )
2021
+ collection .ChannelMapper = channels .NewChannelMapper (ctx , channels .DocChannelsSyncFunction , db .Options .JavascriptTimeout )
2022
+
2023
+ // Create a user with access to channel A
2024
+ authenticator := db .Authenticator (base .TestCtx (t ))
2025
+ user , err := authenticator .NewUser ("alice" , "letmein" , channels .BaseSetOf (t , "A" ))
2026
+ require .NoError (t , err )
2027
+ require .NoError (t , authenticator .Save (user ))
2028
+ collection .user , err = authenticator .GetUser ("alice" )
2029
+ require .NoError (t , err )
2030
+
2031
+ // test get active path by specifying nil cv
2032
+ revBody := Body {"channels" : testCase .docChannels }
2033
+ rev , doc , err := collection .Put (ctx , docID , revBody )
2034
+ require .NoError (t , err )
2035
+ revision , err := collection .GetCV (ctx , docID , nil , true )
2036
+
2037
+ if testCase .access == true {
2038
+ require .NoError (t , err )
2039
+ vrs := doc .HLV .Version
2040
+ src := doc .HLV .SourceID
2041
+ sv := & Version {Value : vrs , SourceID : src }
2042
+ assert .Equal (t , rev , revision .RevID )
2043
+ assert .Equal (t , sv , revision .CV )
2044
+ assert .Equal (t , docID , revision .DocID )
2045
+ assert .Equal (t , []byte (`{"channels":["A"]}` ), revision .BodyBytes )
2046
+ } else {
2047
+ require .Error (t , err )
2048
+ assert .ErrorContains (t , err , ErrForbidden .Error ())
2049
+ assert .Equal (t , DocumentRevision {}, revision )
2050
+ }
2051
+ })
2052
+ }
2053
+ }
0 commit comments