public void CaptureReader_Can_Read_Back_A_Stream_That_Was_Written_By_A_CaptureWriter() { var writeOperations = 100; var ms = new ConcurrentStream(new MemoryStream()); var sat = new Dictionary<Guid, short>(); sat.Add(Guid.NewGuid(), 24); sat.Add(Guid.NewGuid(), 25); sat.Add(Guid.NewGuid(), 26); var stateResolver = new Mock<IStateResolver>(); stateResolver.SetupGet(s => s.AllocationTable).Returns(sat); stateResolver.Setup(s => s.IsAllocated(It.IsAny<Guid>())).Returns<Guid>(g => sat.ContainsKey(g)); stateResolver.Setup(s => s.GetAllocatedId(It.IsAny<Guid>())).Returns<Guid>(g => sat[g]); //write operations var captureWriter = new CaptureWriter(ms, stateResolver.Object); for (int i = 0; i < writeOperations; i++) { var timestamp = DateTime.UtcNow; var randomData = new byte[1024]; new Random().NextBytes(randomData); var randomSat = (short)new Random().Next(24, 26); var captureState = new Mock<ICaptureState>(); captureState.Setup(c => c.Data).Returns(randomData); captureState.Setup(c => c.Guid).Returns(sat.Where(f => f.Value == randomSat).First().Key); captureState.Setup(c => c.Timestamp).Returns(timestamp); captureWriter.Write(captureState.Object); } //rewind the stream to the beginning ms.Position = 0; //read operations var readStateResolver = new StateResolver(); readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 24).First().Key }); readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 25).First().Key }); readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 26).First().Key }); var captureReader = new CaptureReader(ms, readStateResolver); while (captureReader.Position < captureReader.Count) { captureReader.Read(); } }
/// <summary> /// Creates a new instance of the CaptureStream with the specified base stream and mode /// </summary> /// <param name="stream"></param> public CaptureStream(IStream baseStream, System.IO.FileAccess fileAccess, IStateResolver stateResolver) { switch (fileAccess) { case System.IO.FileAccess.Read: { _CaptureReader = new CaptureReader(baseStream, stateResolver); this.Timestamp = _CaptureReader.Timestamp; break; } case System.IO.FileAccess.Write: { _CaptureWriter = new CaptureWriter(baseStream, stateResolver); this.Timestamp = _CaptureWriter.Timestamp; break; } default: { var streamPosition = baseStream.Position; //important to create writer first, it will create the header the reader expects (if required) _CaptureWriter = new CaptureWriter(baseStream, stateResolver); //put the position back to the original position baseStream.Position = streamPosition; //reader now has a valid continuum file to play _CaptureReader = new CaptureReader(baseStream, stateResolver); this.Timestamp = _CaptureWriter.Timestamp; break; } } this.StateResolver = stateResolver; //store the read/write pointers _ReadPointer = baseStream.Position; _WritePointer = baseStream.Position; _Lock = new object(); }
public void CaptureStream_Supports_Reading_A_File_For_Playback_Prior_To_The_Entire_File_Becoming_Available() { //base bytes to feed into the stream at random var bytes = VastPark.FrameworkBase.IO.EmbeddedResource.GetBytes("Continuum.Test.Samples.weather-simulation.continuum", Assembly.GetExecutingAssembly()); var endOfHeader = 0L; using (var ms = new MemoryStream(bytes)) { var reader = new CaptureReader(new ConcurrentStream(ms), new StateResolver()); endOfHeader = reader.BaseStream.Position; } var stream = new MemoryStream(); var baseStream = new ConcurrentStream(stream); var binaryWriter = new BinaryWriter(stream); var stateResolver = new StateResolver(); stateResolver.Add(new Continuum.Test.Mock.WeatherStateController(new WeatherSimulator())); //push in some bytes to get it started, enough for the header so that the stream won't throw on construction binaryWriter.Write(bytes, 0, (int)endOfHeader); var offset = baseStream.Position; baseStream.Position = 0; var captureStream = new CaptureStream(baseStream, FileAccess.Read, stateResolver); Assert.Null(captureStream.Peek()); //write some bytes in (not enough for a full state) binaryWriter.Seek((int)offset, SeekOrigin.Begin); binaryWriter.Write(bytes, (int)offset, 10); offset += 10; Assert.Null(captureStream.Peek()); //write some more bytes so that there is now a full state that can be peeked at binaryWriter.Seek((int)offset, SeekOrigin.Begin); binaryWriter.Write(bytes, (int)offset, 200); Assert.NotNull(captureStream.Peek()); }
public void State_Allocation_Table_Is_Correctly_Populated() { var expectedId = (short)123; var expectedGuid = Guid.NewGuid(); var ms = new ConcurrentStream(new MemoryStream()); var idBytes = BitConverter.GetBytes(expectedId); var guidBytes = expectedGuid.ToByteArray(); //write the header var header = _CreateContinuumHeader(1000, 10000); ms.Write(header.ToArray(), 0, header.Length); //write the SAT ms.Write(BitConverter.GetBytes(1), 0, 4); ms.Write(idBytes, 0, idBytes.Length); ms.Write(guidBytes, 0, guidBytes.Length); //rewind the stream ms.Position = 0; var stateController = new Mock<IStateController>(); var stateResolver = new Mock<IStateResolver>(); stateResolver.Setup(s => s.Find(It.IsAny<Guid>())).Returns(stateController.Object); var captureReader = new CaptureReader(ms, stateResolver.Object); Assert.NotEmpty(captureReader.StateAllocationTable); Assert.Equal(expectedId, captureReader.StateAllocationTable.First().Key); Assert.Equal(expectedGuid, captureReader.StateAllocationTable.First().Value); Assert.Equal(1, captureReader.StateAllocationTable.Count); }
public void Peek_Does_Not_Advance_The_Read_Pointer() { var writeOperations = 100; var ms = new ConcurrentStream(new MemoryStream()); var sat = new Dictionary<Guid, short>(); sat.Add(Guid.NewGuid(), 24); sat.Add(Guid.NewGuid(), 25); sat.Add(Guid.NewGuid(), 26); var stateResolver = new Mock<IStateResolver>(); stateResolver.SetupGet(s => s.AllocationTable).Returns(sat); stateResolver.Setup(s => s.IsAllocated(It.IsAny<Guid>())).Returns<Guid>(g => sat.ContainsKey(g)); stateResolver.Setup(s => s.GetAllocatedId(It.IsAny<Guid>())).Returns<Guid>(g => sat[g]); //write operations var captureWriter = new CaptureWriter(ms, stateResolver.Object); for (int i = 0; i < writeOperations; i++) { var timestamp = DateTime.UtcNow; var randomData = new byte[1024]; new Random().NextBytes(randomData); var randomSat = (short)new Random().Next(24, 27); var captureState = new Mock<ICaptureState>(); captureState.Setup(c => c.Data).Returns(randomData); captureState.Setup(c => c.Guid).Returns(sat.Where(f => f.Value == randomSat).First().Key); captureState.Setup(c => c.Timestamp).Returns(timestamp); captureWriter.Write(captureState.Object); } //rewind the stream to the beginning ms.Position = 0; //read operations var readStateResolver = new StateResolver(); readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 24).First().Key }); readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 25).First().Key }); readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 26).First().Key }); var captureReader = new CaptureReader(ms, readStateResolver); var position = captureReader.Position; var state = captureReader.Peek(sat.Where(f => f.Value == (short)26).First().Key); Assert.NotNull(state); Assert.Equal(position, captureReader.Position); }
public void CaptureReader_Throws_An_Exception_When_Loading_An_Invalid_Continuum_Stream() { //empty stream is considered invalid var baseStream = new ConcurrentStream(new MemoryStream()); var stateController = new Mock<IStateController>(); var stateResolver = new Mock<IStateResolver>(); stateResolver.Setup(s => s.Find(It.IsAny<Guid>())).Returns(stateController.Object); try { var captureReader = new CaptureReader(baseStream, stateResolver.Object); //fail Assert.True(false); } catch { //pass Assert.True(true); } }
public void CaptureReader_Selects_The_Correct_IStateController_During_Reads() { var immlStateController = new Mock<IStateController>(); var immlStateControllerId = (short)100; var immlStateControllerGuid = Guid.NewGuid(); immlStateController.Setup(g => g.Guid).Returns(immlStateControllerGuid); var boneNodeStateController = new Mock<IStateController>(); var boneNodeStateControllerId = (short)123; var boneNodeStateControllerGuid = Guid.NewGuid(); boneNodeStateController.Setup(g => g.Guid).Returns(boneNodeStateControllerGuid); //build 2 different state mappings var ms = new ConcurrentStream(new MemoryStream()); //header var header = _CreateContinuumHeader(1000, 10000); ms.Write(header, 0, header.Length); //sat ms.Write(BitConverter.GetBytes(2), 0, 4); //count //mapping for imml ms.Write(BitConverter.GetBytes(immlStateControllerId), 0, 2); ms.Write(immlStateControllerGuid.ToByteArray(), 0, 16); //mapping for bones ms.Write(BitConverter.GetBytes(boneNodeStateControllerId), 0, 2); ms.Write(boneNodeStateControllerGuid.ToByteArray(), 0, 16); //generate 2 dummy states, one for each controller var firstRandomBytes = new byte[1024]; new Random().NextBytes(firstRandomBytes); ms.Write(BitConverter.GetBytes(immlStateControllerId), 0, 2); ms.Write(BitConverter.GetBytes(DateTime.UtcNow.ToBinary()), 0, 8); ms.Write(BitConverter.GetBytes((int)firstRandomBytes.Length), 0, 4); ms.Write(firstRandomBytes, 0, firstRandomBytes.Length); var secondRandomBytes = new byte[2048]; new Random().NextBytes(secondRandomBytes); ms.Write(BitConverter.GetBytes(boneNodeStateControllerId), 0, 2); ms.Write(BitConverter.GetBytes(DateTime.UtcNow.ToBinary()), 0, 8); ms.Write(BitConverter.GetBytes((int)secondRandomBytes.Length), 0, 4); ms.Write(secondRandomBytes, 0, secondRandomBytes.Length); ms.Position = 0; //perform the reads and verify var stateResolver = new StateResolver(); stateResolver.Add(immlStateController.Object); stateResolver.Add(boneNodeStateController.Object); var captureReader = new CaptureReader(ms, stateResolver); captureReader.Read(); captureReader.Read(); boneNodeStateController.Verify(c => c.Create(It.IsAny<byte[]>(), It.IsAny<DateTime>(), It.IsAny<double>()), Times.Once()); immlStateController.Verify(c => c.Create(It.IsAny<byte[]>(), It.IsAny<DateTime>(), It.IsAny<double>()), Times.Once()); }
public void CaptureReader_Loads_A_Valid_Continuum_Stream() { var satCount = 5; var header = _CreateContinuumHeader(1000, 10000); var sat = _CreateSAT(satCount); var baseStream = new ConcurrentStream(new MemoryStream()); baseStream.Write(header.ToArray(), 0, header.Length); baseStream.Write(sat, 0, sat.Length); baseStream.Position = 0; var stateController = new Mock<IStateController>(); var stateResolver = new Mock<IStateResolver>(); stateResolver.Setup(s => s.Find(It.IsAny<Guid>())).Returns(stateController.Object); var captureReader = new CaptureReader(baseStream, stateResolver.Object); Assert.Equal(satCount, captureReader.StateAllocationTable.Count); }
public void CaptureStream_Supports_Reading_A_File_While_It_Is_Being_Written_From_Another_Thread() { //base bytes to feed into the stream at random var bytes = VastPark.FrameworkBase.IO.EmbeddedResource.GetBytes("Continuum.Test.Samples.weather-simulation.continuum", Assembly.GetExecutingAssembly()); var endOfHeader = 0L; using(var ms = new MemoryStream(bytes)) { var reader = new CaptureReader(new ConcurrentStream(ms), new StateResolver()); endOfHeader = reader.BaseStream.Position; } var stream = new MemoryStream(); var baseStream = new ConcurrentStream(stream); var binaryWriter = new BinaryWriter(stream); var stateResolver = new StateResolver(); stateResolver.Add(new Continuum.Test.Mock.WeatherStateController(new WeatherSimulator())); //push in some bytes to get it started, enough for the header so that the stream won't throw on construction binaryWriter.Write(bytes, 0, (int)endOfHeader); var offset = baseStream.Position; baseStream.Position = 0; var captureStream = new CaptureStream(baseStream, FileAccess.Read, stateResolver); //write in a little more so we don't have a full state yet binaryWriter.Seek((int)offset, SeekOrigin.Begin); //binaryWriter.Write(bytes, (int)offset, 5); //offset += 5; var readStates = 0; var lockObject = new object(); //create a thread to randomly write chunks of bytes into the base stream ThreadPool.QueueUserWorkItem(w => { while (offset < bytes.LongLength) { var bytesToWrite = new Random().Next(1, 200); if (bytesToWrite > bytes.Length - offset) { bytesToWrite = Convert.ToInt32(bytes.LongLength - offset); } lock (lockObject) { binaryWriter.Seek((int)offset, SeekOrigin.Begin); binaryWriter.Write(bytes, (int)offset, bytesToWrite); offset += bytesToWrite; } Thread.Sleep(200); } Assert.Equal(bytes.LongLength, baseStream.Length); lock (lockObject) { binaryWriter.Seek(0, SeekOrigin.Begin); for (int i = 0; i < bytes.LongLength; i++) { Assert.Equal(bytes[i], (byte)baseStream.ReadByte()); } } }); while (captureStream.Position < captureStream.Count) { lock (lockObject) { if (captureStream.Peek() != null) { captureStream.Read(); readStates++; } } } Assert.Equal(captureStream.Count, readStates); }