github.com/ravendb/ravendb-go-client@v0.0.0-20240229102137-4474ee7aa0fa/tests/attachments_revisions_test.go (about)

     1  package tests
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"runtime"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/ravendb/ravendb-go-client"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func attachmentsRevisionsPutAttachments(t *testing.T, driver *RavenTestDriver) {
    16  	var err error
    17  	store := driver.getDocumentStoreMust(t)
    18  	defer store.Close()
    19  
    20  	{
    21  		_, err = setupRevisions(store, false, 4)
    22  		assert.NoError(t, err)
    23  
    24  		names := createDocumentWithAttachments(t, store)
    25  		{
    26  			f := func(t *testing.T, session *ravendb.DocumentSession, revisions []*User) {
    27  				assertRevisionAttachments(t, names, 3, revisions[0], session)
    28  				assertRevisionAttachments(t, names, 2, revisions[1], session)
    29  				assertRevisionAttachments(t, names, 1, revisions[2], session)
    30  				assertNoRevisionAttachment(t, revisions[3], session, false)
    31  			}
    32  			assertRevisions(t, store, names, f, 9)
    33  		}
    34  		{
    35  			// Delete document should delete all the attachments
    36  			f := func(t *testing.T, session *ravendb.DocumentSession, revisions []*User) {
    37  				assertNoRevisionAttachment(t, revisions[0], session, true)
    38  				assertRevisionAttachments(t, names, 3, revisions[1], session)
    39  				assertRevisionAttachments(t, names, 2, revisions[2], session)
    40  				assertRevisionAttachments(t, names, 1, revisions[3], session)
    41  			}
    42  
    43  			cmd := ravendb.NewDeleteDocumentCommand("users/1", nil)
    44  			err = store.GetRequestExecutor("").ExecuteCommand(cmd, nil)
    45  			assert.NoError(t, err)
    46  			assertRevisions2(t, store, names, f, 6, 0, 3)
    47  		}
    48  
    49  		{
    50  			// Create another revision which should delete old revision
    51  			session := openSessionMust(t, store)
    52  			// This will delete the revision #1 which is without attachment
    53  			user := &User{}
    54  			user.setName("Fitzchak 2")
    55  			err = session.StoreWithID(user, "users/1")
    56  			assert.NoError(t, err)
    57  			err = session.SaveChanges()
    58  			assert.NoError(t, err)
    59  			session.Close()
    60  		}
    61  
    62  		{
    63  			f := func(t *testing.T, session *ravendb.DocumentSession, revisions []*User) {
    64  				// This will delete the revision #2 which is with attachment
    65  				assertNoRevisionAttachment(t, revisions[0], session, false)
    66  				assertNoRevisionAttachment(t, revisions[1], session, true)
    67  				assertRevisionAttachments(t, names, 3, revisions[2], session)
    68  				assertRevisionAttachments(t, names, 2, revisions[3], session)
    69  			}
    70  			assertRevisions2(t, store, names, f, 5, 1, 3)
    71  		}
    72  
    73  		{
    74  			session := openSessionMust(t, store)
    75  			// This will delete the revision #2 which is with attachment
    76  			user := &User{}
    77  			user.setName("Fitzchak 3")
    78  			err = session.StoreWithID(user, "users/1")
    79  			assert.NoError(t, err)
    80  			err = session.SaveChanges()
    81  			assert.NoError(t, err)
    82  			session.Close()
    83  		}
    84  
    85  		{
    86  			f := func(t *testing.T, session *ravendb.DocumentSession, revisions []*User) {
    87  				// This will delete the revision #2 which is with attachment
    88  				assertNoRevisionAttachment(t, revisions[0], session, false)
    89  				assertNoRevisionAttachment(t, revisions[1], session, false)
    90  				assertNoRevisionAttachment(t, revisions[2], session, true)
    91  				assertRevisionAttachments(t, names, 3, revisions[3], session)
    92  			}
    93  			assertRevisions2(t, store, names, f, 3, 1, 3)
    94  		}
    95  
    96  		{
    97  			session := openSessionMust(t, store)
    98  			// This will delete the revision #3 which is with attachment
    99  			user := &User{}
   100  			user.setName("Fitzchak 4")
   101  			err = session.StoreWithID(user, "users/1")
   102  			assert.NoError(t, err)
   103  			err = session.SaveChanges()
   104  			assert.NoError(t, err)
   105  			session.Close()
   106  		}
   107  
   108  		{
   109  			f := func(t *testing.T, session *ravendb.DocumentSession, revisions []*User) {
   110  				// This will delete the revision #2 which is with attachment
   111  				assertNoRevisionAttachment(t, revisions[0], session, false)
   112  				assertNoRevisionAttachment(t, revisions[1], session, false)
   113  				assertNoRevisionAttachment(t, revisions[2], session, false)
   114  				assertNoRevisionAttachment(t, revisions[3], session, true)
   115  			}
   116  			assertRevisions2(t, store, names, f, 0, 1, 0)
   117  		}
   118  
   119  		{
   120  			session := openSessionMust(t, store)
   121  			// This will delete the revision #4 which is with attachment
   122  			user := &User{}
   123  			user.setName("Fitzchak 5")
   124  			err = session.StoreWithID(user, "users/1")
   125  			assert.NoError(t, err)
   126  			err = session.SaveChanges()
   127  			assert.NoError(t, err)
   128  			session.Close()
   129  		}
   130  
   131  		{
   132  			f := func(t *testing.T, session *ravendb.DocumentSession, revisions []*User) {
   133  				// This will delete the revision #2 which is with attachment
   134  				assertNoRevisionAttachment(t, revisions[0], session, false)
   135  				assertNoRevisionAttachment(t, revisions[1], session, false)
   136  				assertNoRevisionAttachment(t, revisions[2], session, false)
   137  				assertNoRevisionAttachment(t, revisions[3], session, false)
   138  			}
   139  			assertRevisions2(t, store, names, f, 0, 1, 0)
   140  		}
   141  	}
   142  }
   143  
   144  func attachmentsRevisionsAttachmentRevision(t *testing.T, driver *RavenTestDriver) {
   145  	var err error
   146  	store := driver.getDocumentStoreMust(t)
   147  	defer store.Close()
   148  
   149  	{
   150  		_, err = setupRevisions(store, false, 4)
   151  		assert.NoError(t, err)
   152  
   153  		createDocumentWithAttachments(t, store)
   154  
   155  		{
   156  			session := openSessionMust(t, store)
   157  			bais := bytes.NewBuffer([]byte{5, 4, 3, 2, 1})
   158  			err = session.Advanced().Attachments().StoreByID("users/1", "profile.png", bais, "")
   159  			assert.NoError(t, err)
   160  
   161  			err = session.SaveChanges()
   162  			assert.NoError(t, err)
   163  			session.Close()
   164  		}
   165  
   166  		{
   167  			session := openSessionMust(t, store)
   168  			var revisions []*User
   169  			err = session.Advanced().Revisions().GetFor(&revisions, "users/1")
   170  			assert.NoError(t, err)
   171  
   172  			rev := revisions[1]
   173  			changeVector, err := session.Advanced().GetChangeVectorFor(rev)
   174  			assert.NoError(t, err)
   175  
   176  			{
   177  				revision, err := session.Advanced().Attachments().GetRevision("users/1", "profile.png", changeVector)
   178  				assert.NoError(t, err)
   179  				r := revision.Data
   180  				bytes, err := ioutil.ReadAll(r)
   181  				assert.NoError(t, err)
   182  				assert.Equal(t, len(bytes), 3)
   183  				assert.Equal(t, bytes, []byte{1, 2, 3})
   184  			}
   185  
   186  			session.Close()
   187  		}
   188  	}
   189  }
   190  
   191  func createDocumentWithAttachments(t *testing.T, store *ravendb.DocumentStore) []string {
   192  	var err error
   193  	{
   194  		session := openSessionMust(t, store)
   195  
   196  		user := &User{}
   197  		user.setName("Fitzchak")
   198  		err = session.StoreWithID(user, "users/1")
   199  		assert.NoError(t, err)
   200  
   201  		err = session.SaveChanges()
   202  		assert.NoError(t, err)
   203  
   204  		session.Close()
   205  	}
   206  
   207  	names := []string{
   208  		"profile.png",
   209  		"background-photo.jpg",
   210  		"fileNAME_#$1^%_בעברית.txt",
   211  	}
   212  
   213  	{
   214  		profileStream := bytes.NewBuffer([]byte{1, 2, 3})
   215  		op := ravendb.NewPutAttachmentOperation("users/1", names[0], profileStream, "image/png", nil)
   216  		err = store.Operations().Send(op, nil)
   217  
   218  		assert.NoError(t, err)
   219  
   220  		result := op.Command.Result
   221  		s := *result.ChangeVector
   222  		assert.True(t, strings.Contains(s, "A:3"))
   223  		assert.Equal(t, result.Name, names[0])
   224  		assert.Equal(t, result.DocumentID, "users/1")
   225  		assert.Equal(t, result.ContentType, "image/png")
   226  	}
   227  
   228  	{
   229  		backgroundStream := bytes.NewReader([]byte{10, 20, 30, 40, 50})
   230  		op := ravendb.NewPutAttachmentOperation("users/1", names[1], backgroundStream, "ImGgE/jPeG", nil)
   231  		err = store.Operations().Send(op, nil)
   232  		assert.NoError(t, err)
   233  		result := op.Command.Result
   234  		s := *result.ChangeVector
   235  		assert.True(t, strings.Contains(s, "A:7"))
   236  		assert.Equal(t, result.Name, names[1])
   237  		assert.Equal(t, result.DocumentID, "users/1")
   238  		assert.Equal(t, result.ContentType, "ImGgE/jPeG")
   239  	}
   240  	{
   241  		fileStream := bytes.NewReader([]byte{1, 2, 3, 4, 5})
   242  		op := ravendb.NewPutAttachmentOperation("users/1", names[2], fileStream, "", nil)
   243  		err = store.Operations().Send(op, nil)
   244  		assert.NoError(t, err)
   245  		result := op.Command.Result
   246  		s := *result.ChangeVector
   247  		assert.True(t, strings.Contains(s, "A:12"))
   248  		assert.Equal(t, result.Name, names[2])
   249  		assert.Equal(t, result.DocumentID, "users/1")
   250  		assert.Equal(t, result.ContentType, "")
   251  	}
   252  	return names
   253  }
   254  
   255  func assertRevisions(t *testing.T, store *ravendb.DocumentStore, names []string, assertAction func(*testing.T, *ravendb.DocumentSession, []*User), expectedCountOfAttachments int64) {
   256  	assertRevisions2(t, store, names, assertAction, expectedCountOfAttachments, 1, 3)
   257  }
   258  
   259  func assertRevisions2(t *testing.T, store *ravendb.DocumentStore, names []string, assertAction func(*testing.T, *ravendb.DocumentSession, []*User), expectedCountOfAttachments int64, expectedCountOfDocuments int64, expectedCountOfUniqueAttachments int64) {
   260  	op := ravendb.NewGetStatisticsOperation("")
   261  	err := store.Maintenance().Send(op)
   262  	assert.NoError(t, err)
   263  	statistics := op.Command.Result
   264  
   265  	assert.Equal(t, statistics.CountOfAttachments, expectedCountOfAttachments)
   266  
   267  	assert.Equal(t, statistics.CountOfUniqueAttachments, expectedCountOfUniqueAttachments)
   268  
   269  	assert.Equal(t, statistics.CountOfRevisionDocuments, int64(4))
   270  
   271  	assert.Equal(t, statistics.CountOfDocuments, expectedCountOfDocuments)
   272  
   273  	assert.Equal(t, statistics.CountOfIndexes, 0)
   274  
   275  	{
   276  		session := openSessionMust(t, store)
   277  		var revisions []*User
   278  		err = session.Advanced().Revisions().GetFor(&revisions, "users/1")
   279  		assert.NoError(t, err)
   280  		assertAction(t, session, revisions)
   281  
   282  		session.Close()
   283  	}
   284  }
   285  
   286  func assertNoRevisionAttachment(t *testing.T, revision *User, session *ravendb.DocumentSession, isDeleteRevision bool) {
   287  	metadata, err := session.Advanced().GetMetadataFor(revision)
   288  	assert.NoError(t, err)
   289  
   290  	if isDeleteRevision {
   291  		v, _ := metadata.Get(ravendb.MetadataFlags)
   292  		s := v.(string)
   293  		assert.True(t, strings.Contains(s, "HasRevisions"))
   294  		assert.True(t, strings.Contains(s, "DeleteRevision"))
   295  	} else {
   296  		v, _ := metadata.Get(ravendb.MetadataFlags)
   297  		s := v.(string)
   298  		assert.True(t, strings.Contains(s, "HasRevisions"))
   299  		assert.True(t, strings.Contains(s, "Revision"))
   300  	}
   301  
   302  	hasIt := metadata.ContainsKey(ravendb.MetadataAttachments)
   303  	assert.False(t, hasIt)
   304  }
   305  
   306  func assertRevisionAttachments(t *testing.T, names []string, expectedCount int, revision *User, session *ravendb.DocumentSession) {
   307  	metadata, err := session.Advanced().GetMetadataFor(revision)
   308  	assert.NoError(t, err)
   309  	v, _ := metadata.Get(ravendb.MetadataFlags)
   310  	s := v.(string)
   311  	assert.True(t, strings.Contains(s, "HasRevisions"))
   312  	assert.True(t, strings.Contains(s, "Revision"))
   313  	assert.True(t, strings.Contains(s, "Revision"))
   314  
   315  	attachments := metadata.GetObjects(ravendb.MetadataAttachments)
   316  	assert.Equal(t, len(attachments), expectedCount)
   317  
   318  	// Note: unlike Java, compare them after sorting
   319  	attachmentNames := make([]string, expectedCount, expectedCount)
   320  	for i := 0; i < expectedCount; i++ {
   321  		attachment := attachments[i]
   322  		aname, ok := attachment.Get("Name")
   323  		assert.True(t, ok)
   324  		anameStr, ok := aname.(string)
   325  		assert.True(t, ok)
   326  		attachmentNames[i] = anameStr
   327  	}
   328  
   329  	orderedNames := append([]string{}, names...)
   330  	if len(orderedNames) > expectedCount {
   331  		orderedNames = orderedNames[:expectedCount]
   332  	}
   333  	sort.Strings(orderedNames)
   334  	sort.Strings(attachmentNames)
   335  	assert.Equal(t, orderedNames, attachmentNames)
   336  }
   337  
   338  func TestAttachmentsRevisions(t *testing.T) {
   339  	driver := createTestDriver(t)
   340  	destroy := func() { destroyDriver(t, driver) }
   341  	defer recoverTest(t, destroy)
   342  
   343  	// Those are flaky on mac and mac only. I suspect server issue
   344  	// see https://github.com/ravendb/ravendb-go-client/issues/92
   345  	if runtime.GOOS == "darwin" && !enableFlakyTests {
   346  		return
   347  	}
   348  
   349  	// matches order of Java tests
   350  	attachmentsRevisionsPutAttachments(t, driver)
   351  	attachmentsRevisionsAttachmentRevision(t, driver)
   352  }