public void StorageExceptionOnUploadLeadsToSavedEmptyState() {
            this.SetUpMocks();

            Mock<IFileInfo> fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.Length).Returns(1);
            var fileContent = new byte[1];
            var localFileStream = new MemoryStream(fileContent);

            fileInfo.Setup(f => f.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)).Returns(localFileStream);

            Mock<IDocument> document;
            this.SetupSolveFile(this.localObjectName, this.remoteObjectId, this.parentId, this.lastChangeToken, this.withExtendedAttributes, fileInfo, out document, failsOnUploadContent: true);
            this.RunSolveFile(fileInfo);
            this.storage.VerifySavedMappedObject(MappedObjectType.File, this.remoteObjectId, this.localObjectName, this.parentId, this.lastChangeToken, this.withExtendedAttributes, checksum: this.emptyhash, contentSize: 0);
            this.VerifyCreateDocument();
            fileInfo.VerifySet(f => f.Uuid = It.Is<Guid?>(uuid => uuid != null), Times.Once());
            fileInfo.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
            document.Verify(d => d.SetContentStream(It.IsAny<IContentStream>(), true, true), Times.Once());
            document.Verify(d => d.UpdateProperties(It.IsAny<IDictionary<string, object>>()), Times.Never());
        }
        public void Local1ByteFileAdded([Values(true, false)]bool withExtendedAttributes) {
            this.SetUpMocks(withExtendedAttributes);
            Mock<IFileInfo> fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.Length).Returns(1);
            var fileContent = new byte[1];
            using (var localFileStream = new MemoryStream(fileContent)) {
                byte[] hash = SHA1Managed.Create().ComputeHash(fileContent);

                fileInfo.Setup(f => f.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)).Returns(localFileStream);

                Mock<IDocument> document;
                this.SetupSolveFile(this.localObjectName, this.remoteObjectId, this.parentId, this.lastChangeToken, this.withExtendedAttributes, fileInfo, out document);
                this.RunSolveFile(fileInfo);
                this.storage.VerifySavedMappedObject(MappedObjectType.File, this.remoteObjectId, this.localObjectName, this.parentId, this.lastChangeToken, Times.Exactly(2), this.withExtendedAttributes, null, null, hash, 1);
                this.VerifyCreateDocument();
                if (this.withExtendedAttributes) {
                    fileInfo.VerifySet(f => f.Uuid = It.Is<Guid?>(uuid => uuid != null), Times.Once());
                } else {
                    fileInfo.VerifySet(f => f.Uuid = It.IsAny<Guid?>(), Times.Never());
                }

                fileInfo.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
                document.Verify(d => d.SetContentStream(It.IsAny<IContentStream>(), true, true), Times.Once());
                document.VerifyUpdateLastModificationDate(fileInfo.Object.LastWriteTimeUtc, true);
            }
        }
        public void LocalFileIsUsedByAnotherProcessOnOpenFile() {
            this.SetUpMocks();
            Mock<IFileInfo> fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.Length).Returns(10);
            fileInfo.SetupOpenThrows(new IOException("Already in use by another process"));

            Mock<IDocument> document;
            Assert.Throws<IOException>(() => {
                this.SetupSolveFile(this.localObjectName, this.remoteObjectId, this.parentId, lastChangeToken, true, fileInfo, out document);
                this.RunSolveFile(fileInfo);
            });
            fileInfo.VerifySet(f => f.Uuid = It.Is<Guid?>(uuid => uuid != null), Times.Once());
            this.storage.VerifySavedMappedObject(MappedObjectType.File, this.remoteObjectId, this.localObjectName, this.parentId, this.lastChangeToken, true, checksum: this.emptyhash, contentSize: 0);
            this.VerifyCreateDocument(isEmpty: false);
            fileInfo.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
        }
        public void DoNotWriteLastWriteTimeUtcIfNotNecessary() {
            this.SetUpMocks(true);

            Mock<IFileInfo> fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.Length).Returns(0);

            Mock<IDocument> document;
            this.SetupSolveFile(this.localObjectName, this.remoteObjectId, this.parentId, this.lastChangeToken, this.withExtendedAttributes, fileInfo, out document, false);
            this.RunSolveFile(fileInfo);

            fileInfo.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
        }
        public void LocalFileIsUsedByAnotherProcess() {
            this.SetUpMocks(true);
            var exception = new ExtendedAttributeException();

            Mock<IFileInfo> fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.Length).Returns(0);
            fileInfo.SetupSet(f => f.Uuid = It.IsAny<Guid?>()).Throws(exception);
            Mock<IDocument> document;
            this.SetupSolveFile(this.localObjectName, this.remoteObjectId, this.parentId, this.lastChangeToken, this.withExtendedAttributes, fileInfo, out document);

            var e = Assert.Throws<RetryException>(() => this.RunSolveFile(fileInfo));

            Assert.That(e.InnerException, Is.EqualTo(exception));
            fileInfo.VerifySet(f => f.Uuid = It.Is<Guid?>(uuid => uuid != null), Times.Once());
            this.storage.Verify(s => s.SaveMappedObject(It.IsAny<IMappedObject>()), Times.Never());
            fileInfo.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
        }
        public void LocalFolderAddingFailsBecauseUtf8Character() {
            this.SetUpMocks();
            var transmissionManager = new TransmissionManager();
            var solver = new LocalObjectAdded(this.session.Object, this.storage.Object, this.transmissionStorage.Object, transmissionManager);
            var dirInfo = new Mock<IDirectoryInfo>();
            dirInfo.Setup(d => d.Exists).Returns(true);
            dirInfo.Setup(d => d.Name).Returns(@"รค".Normalize(System.Text.NormalizationForm.FormD));
            var parentDirInfo = this.SetupParentFolder(this.parentId);
            dirInfo.Setup(d => d.Parent).Returns(parentDirInfo);
            this.session.Setup(s => s.CreateFolder(It.IsAny<IDictionary<string, object>>(), It.IsAny<IObjectId>())).Throws(new CmisConstraintException("Conflict"));
            Assert.Throws<InteractionNeededException>(() => solver.Solve(dirInfo.Object, null));

            this.storage.VerifyThatNoObjectIsManipulated();
            this.session.Verify(s => s.CreateFolder(It.Is<IDictionary<string, object>>(p => p.ContainsKey("cmis:name")), It.Is<IObjectId>(o => o.Id == this.parentId)), Times.Once());
            dirInfo.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
            dirInfo.VerifySet(d => d.Uuid = It.IsAny<Guid?>(), Times.Never());
        }
        public void LocalEmptyFileAdded(bool withExtendedAttributes, bool withAlreadySetUuid) {
            this.SetUpMocks(withExtendedAttributes);
            Guid uuid = Guid.NewGuid();
            Mock<IFileInfo> fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.Length).Returns(0);
            if (withAlreadySetUuid) {
                fileInfo.SetupGuid(uuid);
            }

            Mock<IDocument> document;

            this.SetupSolveFile(this.localObjectName, this.remoteObjectId, this.parentId, this.lastChangeToken, this.withExtendedAttributes, fileInfo, out document);
            this.RunSolveFile(fileInfo);

            this.storage.VerifySavedMappedObject(MappedObjectType.File, this.remoteObjectId, this.localObjectName, this.parentId, this.lastChangeToken, this.withExtendedAttributes, checksum: this.emptyhash, contentSize: 0);
            if (withAlreadySetUuid) {
                this.storage.Verify(s => s.SaveMappedObject(It.Is<IMappedObject>(o => o.Guid == uuid)));
            }

            this.VerifyCreateDocument(isEmpty: true);
            if (this.withExtendedAttributes && !withAlreadySetUuid) {
                fileInfo.VerifySet(f => f.Uuid = It.Is<Guid?>(u => u != null), Times.Once());
            } else {
                fileInfo.VerifySet(f => f.Uuid = It.IsAny<Guid?>(), Times.Never());
            }

            fileInfo.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
            document.Verify(d => d.AppendContentStream(It.IsAny<IContentStream>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
        }
        public void LocalAndRemoteFileDatesAreChangedAndLocalDateIsNewerUpdatesRemoteDate() {
            this.InitMocks();
            string fileName = "fileName";
            DateTime lastLocalModification = DateTime.UtcNow.AddDays(1);
            DateTime lastRemoteModification = DateTime.UtcNow.AddHours(1);
            var localFile = new Mock<IFileInfo>();
            byte[] contentHash;
            using (var stream = this.SetUpFileWithContent(localFile, "content", out contentHash, lastLocalModification)) {
                long length = stream.Length;
                var remoteFile = this.CreateRemoteDocument(lastRemoteModification, length, contentHash);
                var mappedObject = new MappedObject(fileName, this.remoteId, MappedObjectType.File, this.parentId, this.oldChangeToken, length) {
                    Guid = Guid.NewGuid(),
                    LastChecksum = contentHash,
                    LastLocalWriteTimeUtc = DateTime.UtcNow,
                    LastRemoteWriteTimeUtc = DateTime.UtcNow,
                    ChecksumAlgorithmName = "SHA-1"
                };
                this.storage.AddMappedFile(mappedObject);

                this.underTest.Solve(localFile.Object, remoteFile.Object, ContentChangeType.NONE, ContentChangeType.NONE);

                remoteFile.VerifyUpdateLastModificationDate(lastLocalModification, Times.Once(), true);
                localFile.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
                this.storage.VerifySavedMappedObject(MappedObjectType.File, this.remoteId, fileName, this.parentId, this.newChangeToken, lastLocalModification: lastLocalModification, lastRemoteModification: lastRemoteModification, checksum: contentHash, contentSize: length);
            }
        }
        public void IgnoreChangesOnNonExistingLocalObject() {
            this.SetUpMocks();
            var localDirectory = new Mock<IDirectoryInfo>();
            localDirectory.Setup(f => f.Exists).Returns(false);

            Assert.Throws<ArgumentException>(() => this.underTest.Solve(localDirectory.Object, Mock.Of<IFolder>()));

            this.storage.Verify(s => s.SaveMappedObject(It.IsAny<IMappedObject>()), Times.Never());
            localDirectory.VerifyThatLocalFileObjectLastWriteTimeUtcIsNeverModified();
            this.manager.VerifyThatNoTransmissionIsCreated();
        }