public void LengthTest() { // static length test using (MemoryStream memstream = new MemoryStream(this.content)) using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) { Assert.AreEqual(this.offset + this.content.Length, offsetstream.Length); } // dynamic length test using (MemoryStream memstream = new MemoryStream()) using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) { Assert.AreEqual(0, memstream.Length); Assert.AreEqual(this.offset, offsetstream.Length); offsetstream.SetLength(200); Assert.AreEqual(200, offsetstream.Length); Assert.AreEqual(200 - this.offset, memstream.Length); Assert.Throws<ArgumentOutOfRangeException>(() => offsetstream.SetLength(50)); Assert.AreEqual(200, offsetstream.Length); Assert.AreEqual(200 - this.offset, memstream.Length); } }
public void ResumeTest() { byte[] inputContent = new byte[100]; long offset = 100; using (var stream = new MemoryStream(inputContent)) using (var offsetstream = new OffsetStream(stream, offset)) { using (var progress = new ProgressStream(offsetstream)) { progress.PropertyChanged += delegate(object sender, System.ComponentModel.PropertyChangedEventArgs e) { var p = sender as ProgressStream; if (e.PropertyName == Utils.NameOf(() => p.Position)) { this.position = (long)p.Position; this.percent = p.Percent.GetValueOrDefault(); } }; progress.Seek(0, SeekOrigin.Begin); Assert.AreEqual(offset, this.position); Assert.AreEqual(50, this.percent); progress.Seek(10, SeekOrigin.Current); Assert.AreEqual(offset + 10, this.position); progress.Seek(0, SeekOrigin.End); Assert.AreEqual(100, this.percent); Assert.AreEqual(offset + inputContent.Length, this.position); progress.Seek(0, SeekOrigin.Begin); progress.WriteByte(0); Assert.AreEqual(offset + 1, this.position); Assert.AreEqual(50.5, this.percent); progress.WriteByte(0); Assert.AreEqual(offset + 2, this.position); Assert.AreEqual(51, this.percent); progress.Write(new byte[10], 0, 10); Assert.AreEqual(56, this.percent); } } }
/// <summary> /// Uploads the file. /// Resumes an upload if the given localFileStream.Position is larger than zero. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <param name="update">Is called on every new chunk, if not <c>null</c>.</param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException"> /// Contains the last successful remote document state. This is needed for continue a failed upload. /// </exception> public override IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { IDocument result = remoteDocument; for (long offset = localFileStream.Position; offset < localFileStream.Length; offset += this.ChunkSize) { bool isFirstChunk = offset == 0; bool isLastChunk = (offset + this.ChunkSize) >= localFileStream.Length; using (var hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using (var chunkstream = new ChunkedStream(hashstream, this.ChunkSize)) using (var offsetstream = new OffsetStream(chunkstream, offset)) using (var transmissionStream = transmission.CreateStream(offsetstream)) { transmission.Length = localFileStream.Length; transmission.Position = offset; chunkstream.ChunkPosition = offset; ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(remoteDocument.Name); if (isLastChunk) { contentStream.Length = localFileStream.Length - offset; } else { contentStream.Length = this.ChunkSize; } contentStream.Stream = transmissionStream; try { if (isFirstChunk && result.ContentStreamId != null && overwrite) { result.DeleteContentStream(true); } result.AppendContentStream(contentStream, isLastChunk, true); HashAlgorithmReuse reuse = hashAlg as HashAlgorithmReuse; if (reuse != null && update != null) { using (HashAlgorithm hash = (HashAlgorithm)reuse.Clone()) { hash.TransformFinalBlock(new byte[0], 0, 0); update(hash.Hash, result.ContentStreamLength.GetValueOrDefault()); } } } catch (Exception e) { if (e is FileTransmission.AbortException) { throw; } if (e.InnerException is FileTransmission.AbortException) { throw e.InnerException; } throw new UploadFailedException(e, result); } } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return result; }
private int DownloadNextChunk(IDocument remoteDocument, long offset, long remainingBytes, Transmission transmission, Stream outputstream, HashAlgorithm hashAlg) { lock(this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } IContentStream contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; using (var remoteStream = contentStream.Stream) using (var forwardstream = new ForwardReadingStream(remoteStream)) using (var offsetstream = new OffsetStream(forwardstream, offset)) using (var progress = transmission.CreateStream(offsetstream)) { byte[] buffer = new byte[8 * 1024]; int result = 0; int len; while ((len = progress.Read(buffer, 0, buffer.Length)) > 0) { outputstream.Write(buffer, 0, len); hashAlg.TransformBlock(buffer, 0, len, buffer, 0); result += len; outputstream.Flush(); } return result; } } }
public void SeekTest() { using (MemoryStream memstream = new MemoryStream(this.content)) using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) { Assert.True(offsetstream.CanSeek); Assert.AreEqual(memstream.CanSeek, offsetstream.CanSeek); Assert.AreEqual(memstream.Position + this.offset, offsetstream.Position); long pos = offsetstream.Seek(10, SeekOrigin.Begin); Assert.AreEqual(110, pos); Assert.AreEqual(10, memstream.Position); pos = offsetstream.Seek(0, SeekOrigin.End); Assert.AreEqual(offsetstream.Length, pos); Assert.AreEqual(memstream.Length, memstream.Position); pos = offsetstream.Seek(0, SeekOrigin.Current); Assert.AreEqual(offsetstream.Length, pos); Assert.AreEqual(memstream.Length, memstream.Position); offsetstream.Seek(10, SeekOrigin.Begin); pos = offsetstream.Seek(10, SeekOrigin.Current); Assert.AreEqual(this.offset + 20, pos); Assert.AreEqual(20, memstream.Position); // negative seek pos = offsetstream.Seek(-10, SeekOrigin.Current); Assert.AreEqual(this.offset + 10, pos); Assert.AreEqual(10, memstream.Position); pos = offsetstream.Seek(-10, SeekOrigin.Current); Assert.AreEqual(this.offset, pos); Assert.AreEqual(0, memstream.Position); // seek into illegal areas Assert.Throws<IOException>(() => { pos = offsetstream.Seek(-10, SeekOrigin.Current); }); Assert.AreEqual(this.offset, pos); Assert.AreEqual(0, memstream.Position); } // Using an unseekable stream should return CanSeek = false var mockstream = new Mock<Stream>(); mockstream.SetupGet(s => s.CanSeek).Returns(false); using (OffsetStream offsetstream = new OffsetStream(mockstream.Object)) { Assert.False(offsetstream.CanSeek); } }
public void ConstructorWithOffset() { using (var stream = new OffsetStream(new Mock<Stream>().Object, 10)) { Assert.AreEqual(10, stream.Offset); } }
public void WriteTest() { // Write one block using (MemoryStream memstream = new MemoryStream()) using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) { Assert.AreEqual(0, memstream.Position); Assert.AreEqual(this.offset, offsetstream.Position); offsetstream.Write(this.content, 0, this.content.Length); Assert.AreEqual(this.content.Length + this.offset, offsetstream.Position); Assert.AreEqual(this.content, memstream.ToArray()); } // Write single bytes using (MemoryStream memstream = new MemoryStream()) using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) { Assert.AreEqual(0, memstream.Position); Assert.AreEqual(this.offset, offsetstream.Position); foreach (byte b in this.content) { offsetstream.WriteByte(b); } Assert.AreEqual(this.content.Length + this.offset, offsetstream.Position); Assert.AreEqual(this.content, memstream.ToArray()); } }
public void ReadTest() { // Read block byte[] buffer = new byte[this.contentLength]; using (MemoryStream memstream = new MemoryStream(this.content)) using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) { Assert.AreEqual(0, memstream.Position); Assert.AreEqual(this.offset, offsetstream.Position); int len = offsetstream.Read(buffer, 0, buffer.Length); Assert.AreEqual(this.contentLength, len); Assert.AreEqual(this.contentLength + this.offset, offsetstream.Position); Assert.AreEqual(this.content, buffer); len = offsetstream.Read(buffer, 0, buffer.Length); Assert.AreEqual(0, len); } }